Eerder deze week coachte ik in een DDD-sessie met Tactical DDD als primaire doelstelling. Tactical als in, de focus op Aggregates, Entities, ValueObjects en dergelijke, en de vraag: "Hoe testen we (onze code) bij het uitvoeren van DDD?" kwam naar boven.
Geweldige kans, want code testen, wanneer je DDD doet, is gewoon bevredigend. De eenvoud ervan betekent dat we in principe White Box Unit Testing kunnen doen.
Het is een must om een Onion-architectuur voor het domein te hebben, omdat we ons dan kunnen concentreren op de bedrijfsregels en problemen met de laad- en opslagstatus kunnen negeren.
Ten tweede - gebruik een functionele programmeerstijl, wat betekent dat u altijd "iets" retourneert (vermijd void) en dat "iets" een typefout of gebeurtenis is.
Voorbeeld van magazijn
In een Warehouse kunnen we een Section hebben waar we Goods opslaan. Goods zijn ValueObjects met een aantal fysieke attributen en een Identifier zoals EAN-nummer. Voor de eenvoud zeggen we dat Goods alleen Weight en ID hebben.
Een sectie heeft een maximaal gewicht (regel om te testen), het magazijn staat geen sectieduplicaten toe (regel om te testen).
Sectie is een Entiteit en Warehouse is een Entiteit Aggregate (root). Op de Root Aggregate leggen we bloot:
fun addSection( id: SectieID ) : Ofwel
fun addGoodsToSection(id: SectionID, goederen: Goederen) : Beide
Al onze unittests hebben dit eenvoudige patroon (de code is opzettelijk gecomprimeerd om deze kort te houden):
@Test
// Gegeven: Geen secties, het toevoegen van sectie zou "SectionAdded" moeten opleveren
val magazijn = WareHouse()
val sectie = Sectie( SectieID("mySectieID"), maxGewicht = 20)
val expectEvent : Ofwel = Ofwel.right(SectieToegevoegd("mijnSectieID"))
// Wanneer
var actueel : Ofwel = warehouse.addSection(sectie)
// Dan
assert(verwachte gebeurtenis, actueel)
// Gegeven: Het toevoegen van een bestaande sectie zou "Fout" moeten opleveren
val expectError : Beide = Either.left( Error("mySectionID bestaat al"))
// Wanneer
actueel = warehouse.addSection(sectionId)
// Dan
assert(verwachtError, actueel)
@Test
// Gegeven een lege sectie met max. 20, zou het toevoegen van goederen met een gewicht van 30 moeten resulteren in een fout
val magazijn = WareHouse()
val sectie = Sectie( SectieID("aSectieID"), maxGewicht = 20)
magazijn.addSection(sectieId)
waarde goederen = Goederen("#EAN:0123456789", 30 )
val expectError : Beide = Ofwel.Left( Error("MaximumGewichtZouOverschrijden"))
// Wanneer
val actueel = warehouse.addGoodsToSection(sectie.id, goederen)
// Dan
assert(verwachtError, actueel)
Eenvoudige test
Omdat we altijd een Response krijgen en we ons niet bezig hoeven te houden met het laden/opslaan van Data, wordt elke test eenvoudig. We kunnen zelfs (misschien niet de beste praktijken) een continue testflow in één keer uitvoeren, zoals getoond in de eerste Test.
Hoe u aggregaten laadt en opslaat (de objectgrafiek met gegevens vult), valt buiten het bestek van dit artikel. Maar zoals altijd geldt: als u vragen hebt of benieuwd bent hoe DDD jou kan helpen, stuur dan gerust een bericht. Ik neem dan contact met je op.
Comments