Inom vårt team fick vi högst prioterat in en bugg som låg mitt i våran domän model, våran prismodell! Detta leder till att en heldrös objekt är inblandade i skapandet av diverse priser. Jag börjde titta på de tester vi har på just på det området inom vår domän och insåg att det var otroligt mycket kod som var duplicerad samt svårtydlig. När sedan bug rättning storyn startade i sprinten tittade jag på olika lösningar inom tdd att arrangera våra fixturer.
Jag såg följande alternativ:
- ObjectMother - en static factory lösning som ger utvecklaren den fixtur som behövs inför sitt enhetstest
- BuilderPattern - en DSL liknande lösning att ge utvecklaren en flexibel fixtur test data lösning baserat på standarn val.
Jag måste ge Nat Pryce super kred! killen är grym! Såg hans exempel på Builder pattern för sina texturer och insåg att detta är det spår vi måste ta.
Efter närmare undersökning så insåg jag att vi redan hadde en hybrid av Object Mother genom en abstract class som inehöll static metoder enligt “create” så som:
createCampaingWithEnclosingBudgetWtihLimitOnClick();Dessa metoder förökade sig som svampar! genom att varje test i sig är unikt, vilket är bra! Dock leder detta till en Object Mother som är mer som en sur gammal mormor.
Genom att i ställer ta en annan approch genom builder-pattern och att ha smarta default-värden. Plus att ge (enligt tips från Nat pryce) Builders i Builders anrop slippa se en harang av build().build().build(), så får man ett fluent dsl i sin test fixtur. Ruskigt fint för ögat samt att man har den trevliga sideffekten att sina test builders kan leva i test sourcen tills man inser att detta borde ligga i produktions koden direkt!
Ett exempel (Campaign är aggregat objekt):
| 1 |
|
| 2 | //Given
|
| 3 | Currency sek = Currency.getInstance("sek");
|
| 4 | Long id = new Long(1L);
|
| 5 | Campaign campaign = aCampaign(id).andCurrency(sek).
|
| 6 | withBudget(aLimit(100L).withEvent(aEvent().asClick())
|
| 7 | .withPrice(50D).build()
|
| 8 | |
En annan sid effekt blir att varje test inte behöver lägga till ett ytterligare createMetod bara pga av ett ytterligare test fixtur. Lägg til buildern med ett smart default värde/builder istället!
Som Josua Bloch propagerar borde varje
new vara inkapslat av en builder, så låt nu dina test builders blir riktiga medlemmar av din domän istället!
Finns ruskigt bra argument varför man ska kapsla in new operatorn! men det i en annan post