Archief ‘Testing’ categorie
Door: Jan-Kees van Andel, 19 April 2009
I really hate the Singleton pattern. It makes code hard to test, it has nothing to do with general OO principles and the Singletons I see daily (written by others of course ) usually look very procedural.
People who use Singletons in Java all the time have more fundamental problems (I’m not talking about singleton scope in Spring btw), so I’m not gonna rant about that problem here, but I do like to show you an alternative which makes it easier to unit test Singletons.
Neal Ford published a talk on InfoQ called: “10 Ways to Improve Your Code”. Item 4: “Good citizenship” is about static methods and especially the Singleton design pattern. Static methods have their usage, for example simple stateless utilities like: int Math.sqrt(double) or Apache Commons. But when you’re going to add state into the mix, things get messy.
Singleton usage
Let’s step back. Why are we using Singletons in the first place?
- First, as the name says, because you want to guarantee that there is only one instance. Typical examples in the Java libraries are java.awt.Toolkit and java.io.Console.
For those of you interested, Console doesn’t have a static getConsole method, but can be accessed through System.console() and – in the Sun implementation – SharedSecrets.getJavaIOAccess().console(). In these cases, a Singleton is needed because there may NEVER be two instances of these classes. Otherwise strange things will happen, because you never know which instance contains the state you need.
- Second, and depending on the circumstances this is a good or a bad thing, Singletons are the Object Oriented equivalent of globals. Almost everybody agrees that (non-immutable) globals are very bad, but for some reason, many developers still use Singletons. But, for certain objects, it’s useful to be able to access them from everywhere, without needing parameters all the time.
And of course, there are plenty of myths regarding Singletons, for example because singletons can be lazily instantiated on first use. Well, guess what? Classes are lazily initialized by the ClassLoader, so unless you’re messing with cyclic initialization dependencies you don’t need any custom lazy loading mechanism.
By the way, lazy initialization is a bad thing that should be avoided if possible. See Joshua Bloch’s Effective Java for more details.
An example Singleton
Below is a snippet with an example Singleton. You probably see Singletons like this all day.
public final class BadSingleton {
private final String prop1;
private final String prop2;
private BadSingleton() {
this.prop1 = System.getProperty("prop1");
this.prop2 = System.getProperty("prop2");
}
private static final BadSingleton INSTANCE = new BadSingleton();
public static BadSingleton getInstance() {
return INSTANCE;
}
// Other methods
}
It’s just a simple Singleton. It uses field initialization for thread safety and simplicity, but is still lazily initialized (by the ClassLoader). Further, initialization is done in the constructor where the environment is queried for some settings.
As you might know, this code is not testable, not even with reflection/setAccessible(true) hacking, since the field is declared static + final. See the following snippet for a misguided attempt to create a unit test:
public class BadSingletonTest {
@Test
public void testGetInstance_Fail() throws Exception {
Constructor<BadSingleton> constructor = BadSingleton.class.getDeclaredConstructor();
constructor.setAccessible(true);
BadSingleton obj1 = constructor.newInstance();
Field field = BadSingleton.class.getDeclaredField("INSTANCE");
field.setAccessible(true);
field.set(null, obj1); // Exception because INSTANCE is static + final
BadSingleton obj1 = BadSingleton.getInstance();
BadSingleton obj2 = BadSingleton.getInstance();
Assert.assertSame(obj1, obj2);
}
}
An alternative for this issue would be lazy initialization, but this has the disadvantages of not being thread safe when not synchronized correctly. Java Concurrency in Practice by Brian Goetz is a must-read when you are interested in thread safety issues.
Alternative using a factory
This is the alternative Singleton class. It’s a modified version of Neal’s example.
public final class GoodSingleton {
private final String prop1;
private final String prop2;
private GoodSingleton(String prop1, String prop2) {
this.prop1 = prop1;
this.prop2 = prop2;
}
// Other methods
}
The responsibility of instantiating the Singleton is programmed into the Factory, which is shown below:
public class GoodSingletonFactory {
private static final GoodSingleton INSTANCE;
static {
try {
String prop1 = System.getProperty("prop1");
String prop2 = System.getProperty("prop2");
Constructor<GoodSingleton> constructor = GoodSingleton.class.getDeclaredConstructor(String.class, String.class);
constructor.setAccessible(true);
INSTANCE = constructor.newInstance(prop1, prop2);
} catch (Exception e) {
throw new RuntimeException("error initializing " + GoodSingletonFactory.class.getName(), e);
}
}
public static final GoodSingleton getInstance() {
return INSTANCE;
}
}
As shown in the snippet, the factory uses reflection to access the private constructor. Note that this trick only works if there is no SecurityManager or if the active SecurityManager approves this action.
It’s also a little bit less “Singleton” since it is possible to have more than one instance. The same reflection trick we used, now works a bit against us. If this is not an issue for you, it doesn’t matter. After all, developers who want to abuse your API always succeed if they really want to.
But we do get the advantage of better testability, as shown in the following two snippets:
public class GoodSingletonTest {
@Test
public void testConstructor_Ok() throws Exception {
Constructor<GoodSingleton> constructor = GoodSingleton.class.getDeclaredConstructor(String.class, String.class);
constructor.setAccessible(true);
GoodSingleton obj1 = constructor.newInstance("1", "2");
// Assert stuff
}
}
public class GoodSingletonFactoryTest {
@Test
public void testGetInstance_Only_one_instance() throws Exception {
System.setProperty("prop1", "test value");
System.setProperty("prop2", "test value");
GoodSingleton instance1 = GoodSingletonFactory.getInstance();
Assert.assertNotNull(instance1);
GoodSingleton instance2 = GoodSingletonFactory.getInstance();
Assert.assertNotNull(instance2);
Assert.assertSame(instance1, instance2);
}
}
As you can see, testing now becomes trivial.
Notes
Choosing the factory approach has some effects that may be important to you. Here’s a list of consequences and random thoughts.
- When using the reflection approach, it is possible for developers to mess up the Singleton behavior using reflection. When they do this, you may end up with multiple instances, which may be undesirable. When using a Singleton and the instance field is declared as static + final, this is not possible. The importance of this point differs per situation.
- You can choose to make the constructor package private (default) accessible. This way, you don’t need reflection to access it from the same package. If you put the Factory and the unit tests in the same package, this will make the code much more readable, especially for less experienced developers. It’s also less error prone, because the compiler isn’t capable of doing thorough checks on reflective code. On the other hand, if a developer put’s a custom class in the same package, it’s possible to invoke the constructor and thus create multiple instances.
- There is a myth that reflection is slow. It’s true that reflection is not as fast as JIT optimized (plain Java) bytecode. But since about 2000, there have been massive improvements in reflective invocation performance. And of course, if you look at the snippets, reflection is only used the first time.
- Using a static initializer block in the Factory and an immutable (all fields final, no lazy initialization) Singleton class makes the entire structure less sensitive to Concurrency hazards. Again, see Brian Goetz’ book for details.
If you ask me, the advantages outweigh the disadvantages by miles, especially when you consider that when developers misbehave (like in the first two bullets) in such a way that they break the Singleton principle, they should (and on my projects will) be ass whooped.
Gepost in Testing, patterns | 12 reacties »
Door: Pieter van Boxtel, 19 February 2009
In de huidige versie van de Referentie Architectuur hebben we verklaard aanhanger te zijn van Domain Driven Design. We hebben domein objecten gedefinieerd, maar wat doen we nu eigenlijk met het gedachtengoed van Evans? Een van de doelen voor de volgende versie is te kijken of we de patterns van DDD een plekje kunnen geven. Hieronder een poging daartoe, waarbij ik niet al te veel beschrijving of uitleg van de patterns geef. Voor een goede uitleg van de patterns is een niet te overtreffen bron, en dat is het boek van Evans.
Evans beschijft eigenlijk twee soorten patterns. De eerste soort geeft een onderscheid in typen objecten en methoden. Deze patterns zijn concreet terug te zien in een domein model. Dit zijn de patterns waar we echt iets mee kunnen in de referentie architectuur. De tweede soort zijn eerder proces patterns. Deze beschrijven wat abstractere doelen en wegen naar deze doelen. Deze patterns zijn moeilijk concreet te maken in een referentie architectuur en ze komen hier verder niet meer aan bod.
Kern van een DDD domein model zijn Entities (89) en Value Objects (97). Dit zijn de klassieke OO objecten met een toestand en gedrag. Entities zijn objecten met een “identiteit”. Ze zijn niet uitwisselbaar. Ze kunnen gedurende hun levensduur veranderen, maar ze blijven uniek. Een persoon object is in de regel een Entity. Een persoon wordt ouder, zijn uiterlijk verandert, allerlei attributen wijzigen, maar een persoon blijft dezelfde identiteit. Value Objects daarentegen zijn wel uitwisselbaar. In een klantencontactsysteem is een adres niets meer dan een verzameling attributen. Een adres object kan hergebruikt worden, maar dat hoeft niet. Het maakt niet uit als in het systeem twee adres objecten geïnstantieerd zijn met hetzelfde adres. En als een persoon en zijn adres uit memory verdwijnen, dan is het wanneer de persoon opnieuw opgevraagd wordt niet belangrijk dat hetzelfde adres object teruggevonden wordt. (Voor een kadastraal systeem gaat deze redenatie uiteraard niet op…)
Onderscheid tussen Entities en Value Objects is waardevol bij het ontwerp van een applicatie. We kunnen andere ontwerpregels op deze typen objecten loslaten. Zo is het een goed idee om Value Objects immutable te maken. Wanneer een attribuut dient te wijzigen vervangen we het object gewoon door een nieuwe instantie. Fowler definieerde het onderscheid tussen Entities en Value Objects al in Patterns of Enterprise Application Architecture. Hij lijkt Value Objects echter te suggereren voor algemene, herbruikbare zaken, zoals Money. Evans gebruikt het onderscheid structureler door elk “klassiek” domein object in een van beide hokjes te duwen. Bijvoorbeeld in een facturatie systeem kunnen we facturen modelleren als Entities en factuurregels als Value Objects.
Ook geeft Evans enkele richtlijnen voor het opstellen van Entities en Value Objects:
- Gebruik Intention-Revealing Interfaces (246), waarbij namen van klassen en methoden hun effect en doel beschrijven.
- Gebruik Side-Effect-Free Functions (250), factor deze uit in Value Objects en maak er Closed Operations (268) van.
- Maak daarentegen van Entity methodes die de state wijzigen commands die geen domein klassen teruggeven. Gebruik Assertions (255) om post-condities en invarianten van deze methodes te controleren.
Services (104) zijn objecten met enkel gedrag. Ze bevatten methoden die geen logische plek hebben in een Entity of Value Object. De naam ‘Service’ is enigszins verwarrend aangezien de term ’service’ in de Referentie Architectuur en andere architecturen in een andere context gebruikt wordt. Een betere naam is wellicht ‘Domain Service’.
Entities en Value Objects zijn de objecten in het domein model die gepersisteerd worden. Factories (136) en Repositories (147) zijn de domein objecten die voor persistentie verantwoordelijk zijn. Factories creëren domein objecten en Repositories bieden zoek-ingangen. Een Factory is in feite geen afzonderlijk type object. Een Factory wordt gerealiseerd door middel van een Factory Method (GoF) op een Entity of op een al dan niet speciaal voor het doel gecreëerde Service. Door vanuit de Factory Method te delegeren naar een ‘add’ methode op een Repository bewerkstelligen we dat database logica in één type domeinobject gecentreerd wordt.
De eenheid voor persistentie is een Aggregate (125). Dit is verzameling van een of meerdere entities en value objects, waarbij één entity, de root, als aanspreekpunt fungeert. Alle niet-root objecten in de aggregate staan uitsluitend ter dienste van de root en objecten buiten de aggregate hebben uitsluitend relaties naar de aggregate root.
Verder kunnen domeinobjecten gegroepeerd worden in Modules (109), om zodoende structuur te creëren in het domeinmodel. Modules of Packages zijn standaard concepten in OO programmeertalen en modelleertechnieken.
Een Specification (224) tenslotte is een eenvoudig Value Object dat een (of meerdere) business rule controleert voor een ander object. Specifications zijn gebaseerd op predicatenlogica waardoor ze als logische condities zijn te combineren tot complexere business rules. Een Specification kan drie doelen hebben:
- Validatie van een business rule op een object. Een toepassing hiervan is de manier waarop Mod4J met business rules in de domein DSL omgaat.
- Een selectie criterium specificeren om een object uit een selectie te selecteren. Een toepassing hiervan is gebruik van een Specification als parameter voor een Repository.
- Bouw van een nieuw object specificeren.
Onderstaand plaatje toont bovenstaande patterns en hun relaties:

De hierboven genoemde patterns kunnen we zonder al te grote gevolgen in de referentie architectuur opnemen ter vervanging van / uitbreiding op de huidige typen business componenten. De vertaling gaat dan als volgt:
- De huidige Referentie Architectuur kent Business Processen, welke vergelijkbaar lijken met Domain Services. Business Processen zijn echter geen onderdeel van het domein model, ze worden niet aangeroepen door domein objecten. Verder stelt de Referentie Architectuur dat elke aanroep van een domein object via een business process gaat. In feite hebben we met deze Business Processen een extra “laagje” gecreëerd dat redundant is, aangezien erboven zich een verplichte servicelaag bevindt. Niets let ons om dat laagje te schrappen en domain services alleen te definieren als ze een toegevoegde waarde hebben.
- De domein objecten zoals we ze nu kennen kunnen we onderverdelen in Entities en Value Objects.
- Aggregates worden nu wel genoemd in de implementation view als eenheid van persistentie, maar ze worden niet expliciet onderkend als modelleereenheid in de logische view.
- Specifications zijn nieuw ten opzichte van de referentie architectuur, hoewel Mod4J ze wel al toepast voor business rules.
- Repositories zitten nu in een afzonderlijke laag, de datalaag, en heten Data Access Logic component. Echter, zoals ik in een vorige blog betoogde is dat niet terecht en horen ze in de domeinlaag thuis.
- Volgens diezelfde blog zijn de Service Agents en Data Service Agents zoals we ze nu kennen dezelfde dingen en kunnen we ze onderbrengen in een (nieuwe) laag, de Integratielaag.
Mijn conclusie is dat we door toepassing van de DDD patterns de referentie architectuur consistenter en begrijpelijker kunnen maken. In het ontwerp van een applicatie komt meer structuur, terwijl het resultaat, de implementatie, nagenoeg niet wijzigt ten opzichte van de huidige referentie architectuur. Bijkomend voordeel van toepassing van DDD is dat we voor de educatie van de architectuur kunnen verwijzen naar het boek “Domain Driven Design” van Evans.
Gepost in Algemeen, Architectuur, Testing | 1 reactie »
Door: Hedzer Westra, 21 January 2009

Auteur: Steve McConnell, publicatiejaar: 2004, pagina’s: 906, ISBN-13: 978-0735619678, website: http://www.cc2e.com/, Amazon rating: 5 sterren.
Code Complete was me jaren geleden aangeraden als hét boek (‘de bijbel’) om te leren nette code te produceren. Enige tijd geleden (!) is de tweede editie uitgekomen, wat me een goed moment leek om deze eens te bestuderen. Het viel me gelijk op dat deze dikke pil van Microsoft Press afkomstig is; auteur Steve McConnell komt uit de (Microsoft) wereld van C-programmeurs, maar beheerst vele andere talen.
Het boek geeft de lezer diverse praktische, aan de praktijk gestaafde, gedetailleerde tips en voorbeelden om op een juiste manier programmacode te maken. De meeste voorbeelden gaan uit van C++, Visual Basic, Java en C# (in die volgorde). Daar zit ’m wat mij betreft ook meteen een manco: ikzelf ben niet (meer) geïnteresseerd in allerlei tips om onder anderen netjes met pointers en globale variabelen om te gaan. Dat heeft Java netjes voor me afgeschermd… Wel krijg je een interessant kijkje in de keuken van C/C++, en wat extra respect voor programmeurs daarin, die zelfdiscipline nodig hebben, waar wij de taal Java hebben om dezelfde mate van noodzakelijke restrictie te krijgen.
De structuur, lay-out en leesbaarheid van het boek is zeer goed: er is op een prettig leesbare manier geschreven, hier en daar humoristisch en nergens flauw. Een uitgebreide inhoudsopgave, lijst van tabellen & figuren, referenties, leeslijst van tijdschriften en boeken, en index ontbreken niet. Elk hoofdstuk begint met een duidelijke inleiding van de inhoud, en eindigt met een checklist, samenvatting van de ‘key points’ en vele referenties naar extra leesvoer. Dat laatste is erg opvallend: Steve heeft ontzettend veel materiaal gebruikt bij het samenstellen van dit boek. In het voorwoord claimt hij dan ook dat zijn boek een samenvatting is van heel veel (zo niet alle) succesvolle ontwikkelingen en ontdekkingen op het gebied van softwareconstructie. Overal in het boek staan in de kantlijn referenties naar de ‘cc2e’ website met meer informatie, betekenisvolle quotes van bekende IT-goeroes en kruisverwijzingen. Naast verwijzingen naar onderzoeksresultaten van academici, veelal met statistische gegevens, put de auteur ook uit zijn eigen rijke ervaringen bij o.a. Microsoft, Boeing en NASA. Veel stukken code worden begeleid door een “coding horror” icoontje, om aan te geven hoe verschrikkelijk het desbetreffende antivoorbeeld is.
Het boek omvat 6 delen, onderverdeeld in 35 hoofdstukken, elk met hun eigen onderwerp. Teveel om allemaal te noemen, maar enkele sappige details & citaten wil ik je niet onthouden:
- “Software Construction is the only activity that is guaranteed to be done”: dit is een stevig argument voor Agile werken – waarin documentatie een ondergeschikte rol krijgt toebedeeld ten gunste van productie van programmacode.
- “Program into, not in, a language”: hiermee wil Steve je aanzetten om de mogelijkheden van je taal wijselijk te gebruiken, en niet blind alle mogelijkheden – al dan niet op een verkeerde wijze – toe te passen.
- De sectie over complexiteit en het beperkte menselijke begripsvermogen is erg vermakelijk.
- “Don’t optimise your code, unless a profiler or production problem forces you to.”
- Als alternatief voor nette UML ontwerpen: neem foto’s van tekeningen op whiteboard, of bewaar flip-overs.
- Itereer je design.
- Gebruik tijdens ontwikkeling asserts of excepties die je programma hard doen crashen, maar zorg dat in de productieversie dezelfde fout netjes (liefst zonder interactie van, en overlast voor, de gebruiker) wordt afgehandeld. Dit wordt ook wel offensive vs. defensive programming genoemd.
- Schrijf alles altijd uit in pseudo-code. Persoonlijk doe ik dit zeer zelden – en ik heb uit dit boek ook geen extra stimulans daarvoor gehaald, onder anderen door het detailniveau dat wordt aangeraden.
Veel van de onderwerpen die beschreven worden – requirements, design, optimalisatie, naming convention, (unit) testing, Design Patterns, encapsulatie, factorisatie, assert vs. excepties vs. unit tests, continuous integration, comments vs. refactoring – waren eerlijk gezegd een samenvatting van wat ik al wist. Nuttig om hier en daar iets nieuws te horen, of om even opgefrist te worden, maar echt iets fundamenteels geleerd: nee.
Wat pijnlijk duidelijk wordt, is dat het boek geschreven is vlak voordat Java5 uitkwam – hier en daar wordt Java verweten enkele mogelijkheden te ontberen, terwijl we die al jaren tot onze beschikking hebben.
Concluderend: het boek maakt wat mij betreft zijn belofte slechts gedeeltelijk waar. Voor C++/C#/VB programmeurs is het vast en zeker erg bruikbaar, maar voor Java is het net iets te oud, en ligt er te weinig focus op problemen in Java. Als je junior of medior bent, of voor een breed scala aan onderwerpen in software constructie met één boek klaar wilt zijn, is het een goed boek, maar helaas geen uitstekend boek…
Kleurindicatie: Amber (2 op schaal van 3)
Hierbij nodig ik al mijn collega’s uit om ook boekbesprekingen te publiceren op de J-Tech blog, en tevens informatie te plaatsen op de Wiki (https://wiki.ordina.nl/confluence/display/GENBIEB/Alle+Boeken), zodat iedereen een goede keus kan maken uit de vele boeken waarmee je je vaardigheden en kennis kunt uitbreiden. Ikzelf hoop binnenkort te komen met een bespreking van “Programming in Scala,” het eerste boek over deze nieuwe en spannende programmeertaal.
Hedzer Westra

Gepost in Boeken, Debugging, Methodologieën, Testing, patterns | 1 reactie »
Door: Ron Thijssen, 24 April 2008
Unit tests hebben zichzelf allang bewezen. Ze zijn erg krachtig doordat ze in een korte cyclus feedback kunnen geven over de kwaliteit van je code. Door continuous integration pakketten in te zetten, word je nog eens persoonlijk erop gewezen dat de code wijziging die je zojuist doorgevoerd hebt geen nieuwe fouten heeft geïntroduceerd. Ontwikkelaars maken immers nooit fouten
Zoals het hoort plaatst iedere ontwikkelaar zijn business logic netjes in services en de data acces komt netjes in Data Access Objects. In dit voorbeeld wil ik laten zien hoe je op functioneel niveau je code kan testen zonder dat hier data access voor nodig is. Dus met de constraint dat de code niet met de database mag communiceren. Aangezien we framework freaks zijn en we allemaal Spring gebruiken vanwege dependency injection en het assembleren van objecten gaan we dit ook toepassen in onze testcases. We hebben onze bean definities namelijk al tot onze beschikking. Hierin staan bijvoorbeeld services, dao’s, iterators, processors.
We beginnen even met een voorbeeldje van een testcase.
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:services.xml", "classpath:data.xml"})
public class ServiceTest extends TestCase{
@Autowired
private LoginService loginService;
@Test
public void login() {
User result = loginService.login("Test", "Test");
assertEquals(result.getUsername(), "Test");
}
}
Op dit moment krijgt de LoginService een HibernateUserDaoImpl geïnjecteerd om mee te communiceren. Maar omdat we geen data access willen moeten we deze UserDao vervangen. We komen helaas niet weg met het maken van een DAO-stub. Voor UPDATE en INSERT statements zou het eventueel kunnen, maar zodra een query een bepaalde resultset terug moet geven hang je. We moeten dus een nieuwe UserDao maken met afwijkend gedrag. Kortom; mocken. Nu kunnen we zelf een nieuwe TestUserDaoImpl maken, maar dit introduceert een extra class per testcase (mits we het gedrag van de TestUserDaoImpl willen kunnen veranderen per testcase.) Een betere optie is om gebruik te maken van het mocking framework EasyMock.
Middels EasyMock kunnen we eenvoudig mock objecten maken en declaratief van gedrag voorzien. Het instantiëren van een mock object is relatief eenvoudig:
UserDao userDao = EasyMock.createMock(UserDao.class);
vervolgens kunnen we met expect scripts het gedrag van de userDao aanpassen. Vervolgens zullen we handmatig deze userDao in onze loginService moeten injecteren….
Maar laat Spring daar nu juist net zo goed in zijn. Je raadt het al; we gaan Spring gebruiken om mock objecten te injecteren.
We beginnen met het maken van een bean configuratie die we enkel voor test gaan gebruiken:
<bean id="userDao" class="org.easymock.EasyMock"
factory-method="createMock">
<constructor-arg value="nl.ordina.dao.UserDao" />
</bean>
Bovenstaande bean configuratie maakt gebruik van de factory-method argument, waardoor Spring objecten kan instantiëren middels een factory method. In dit geval is dat EasyMock.createMock(Class<T> class); Als constructor-argument hoeven we enkel de fully qualified classname mee te geven. Spring zal automatisch deze waarde parsen naar een Class. Omdat de UserDao een interface is gebruiken we org.easymock.EasyMock. Indien je een class wil mocken gebruik dan de classextension package van EasyMock.
Als we nu naar onze testcase gaan kijken ziet deze er als volgt uit.
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:services.xml", "classpath:test-data.xml"})
public class ServiceTest extends TestCase{
@Autowired
private LoginService loginService;
@Autowired
private UserDao userDao;
@Test
public void login() {
User result = loginService.login("Test", "Test");
assertEquals(result.getUsername(), "Test");
}
}
De @ContextConfiguration annotatie hebben we aangepast om gebruik te maken van onze test-data.xml configuratie in plaats van de data.xml. Vervolgens laten we Spring de userDao injecteren.
Vervolgens kunnen we het gedrag van de userDao gaan specificeren.
@Before
public void mockSetup() {
User testUser = new User("Test", "User");
expect(userDao.findBy(isA(String.class), isA(String.class))).andReturn(testUser).once();
replay(userDao);
}
@After
public void mockRest() {
reset(userDao);
}
Ik gebruik de @Before en @After annotaties van JUnit 4 welke respectievelijk voor en na de testcase aangeroepen worden. We laten userDao.findBy() nu een vooraf gedefinieerde User retourneren welke we kunnen gebruiken om de daadwerkelijk functionaliteit van de overige services te testen.
Een aantal opmerkingen:
- Let op bij het gebruiken van scope=”prototype” voor de MockBeans. Alle beans die hier gebruik van maken krijgen ieder een nieuwe instantie, zonder gedrag.
- Gebruik een tearDown method om de mockobjecten te resetten. Andere beans zullen tegen dezelfde mock aanpraten met het door jouw gespecificeerde gedrag.
Happy testing!
Gepost in Testing, Tools/Frameworks | 1 reactie »
Door: Jethro Bakker, 19 February 2008
Zoals je misschien weet zijn er in Spring 2.5 veel nieuwe annotaties geintroduceerd. Enkele nieuwe annotaties zijn: @Service, @Component en @Autowird. Wat maar weinig mensen weten is dat je deze annotaties ook in kunt zetten in je testklasses. Dit wordt mogelijk gemaakt door het TestContext framework. Het TestContext framework maakt het bijvoorbeeld mogelijk om de annotatie @Autowired te gebruiken in een testklasse. (Zie onderstaand voorbeeld)
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@TransactionConfiguration(transactionManager="txManager")
public class BlogServiceTests {
@Autowired
private BlogService blogService;
...
}
Wat meteen opvalt is dat deze testklasse niet overerft van AbstractDependencyInjectionSpringContextTests of AbstractTransactionalSpringContextTests. Hiervoor in de plaats gebruik je nu de annotatie @ContextConfiguration en TransactionConfiguration.
Deze klasse kan runnen omdat er een annotatie @RunWith is toegevoegd. Dit is een annotatie uit het JUnit4 framework. Met behulp van deze annotatie wordt JUnit op de hoogte gebracht van het Spring TestContext framework.
Dit voorbeeld is makkelijk uit te breiden met extra annotaties zoals bijvoorbeeld:
@DirtiesContext – Geeft aan dat een test de Spring context vervuild en zorgt ervoor dat de context opnieuw wordt opgebouwd voor de volgende test.
@Transactional, @NotTransactional, @Rollback, @BeforeTransaction, en @AfterTransaction om transactie management te sturen.
Een volledig voorbeeld van een test:
@org.junit.runner.RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@TransactionConfiguration(transactionManager="txManager", defaultRollback=true)
@Transactional
public class BlogServiceTests {
@Autowired
private BlogService blogService;
@Test
@DirtiesContext
@NotTransactional
public void testGetMostRecent(){
List<entry> entries = blogService.getMostRecentEntries();
assertEquals(0, entries.size());
}
....
Het schrijven van integratietesten wordt door het TestContext framework een stuk vereenvoudigd. Annotaties die je in je programmacode gebruikt kun je nu ook je testklasses gebruiken. Voor meer info verwijs ik je naar de referentie documentatie en de broncode van Spring 2.5. Enjoy!
Gepost in Testing, Tools/Frameworks | Geen reacties »
Door: Jan-Kees van Andel, 15 January 2008
Situatie
Je hoort vaak het argument dat JSF erg geschikt is voor unit testen. Meer dan bijvoorbeeld Struts. Ik denk dat dat erg meevalt en nog steeds erg afhankelijk is van hoe je je code programmeert.
Een veelgehoord argument is dat JSF Action methods, Converters, etc. geen dependencies hebben naar de Servlet API, waardoor deze goed in isolatie te testen zijn. In veel gevallen is dit argument onzin, aangezien het grootste verschil de manier is hoe je eraan komt. In veel andere frameworks worden Servlet klassen zoals HttpServletRequest en HttpServletResponse gewoon als parameter doorgegeven aan je actions, terwijl je ze in JSF opvraagt via de FacesContext verzamelbak. De dependency blijft, behalve dat hij in JSF niet expliciet wordt meegegeven. (more…)
Gepost in Testing, Tools/Frameworks | 4 reacties »
| |