Efficiënt unit testen met xUnit en AutoFixture

In softwareontwikkeling speelt het testen van code een cruciale rol in het waarborgen van kwaliteit en het voorkomen van bugs. Een veelgebruikte methode is unit testing, waarbij individuele onderdelen van de code, zoals functies of methoden, worden getest in een afgebakende context. In de .NET-wereld zijn xUnit en AutoFixture krachtige tools om het testen te optimaliseren. Deze blogpost biedt een introductie in hoe je deze tools kunt inzetten om efficiënter unit testen te schrijven.

1. Unit Testing

Unit testing houdt in dat je kleine stukjes code, vaak op methodeniveau, afzonderlijk test. Dit gebeurt in een strikt afgebakende context, bekend als de System Under Test (SUT). Het doel is om fouten in een vroeg stadium op te sporen en de codekwaliteit te verhogen. Bij unit testen maak je vaak gebruik van mocking frameworks zoals Moq, Rhino Mocks of FakeItEasy om afhankelijkheden te simuleren en te controleren of je code correct functioneert zonder dat deze afhankelijk is van andere systeemonderdelen.

2. xUnit

xUnit is een populair, open-source framework voor het schrijven van unit testen in .NET. Het biedt een aantal voordelen:

  • Parallelle testuitvoering: tests kunnen gelijktijdig worden uitgevoerd, wat de snelheid verhoogt.
  • Goede integratie met populaire ontwikkeltools en IDE’s.

Binnen xUnit kan je twee soorten testen schrijven met behulp van specifieke attributen:

  • Fact: Dit attribuut wordt gebruikt voor een simpele testmethode zonder parameters.

  • Theory: Met dit attribuut kan je geparametriseerde testmethodes schrijven met behulp van het InlineData-attribuut om de verschillende scenario’s aan mee te geven.

3. AutoFixture

Het handmatig schrijven van testdata kan tijdrovend en foutgevoelig zijn. AutoFixture is een open-source framework dat automatisch testdata genereert. Het vermindert boilerplate code en maakt je testen refactoring-safe, wat betekent dat je minder snel falende testen introduceert bij codeaanpassingen.

3.1 Basisfunctionaliteiten

3.1.1 Create

Hiermee genereer je automatisch objecten met anonieme data.

3.1.2 CeateMany

Dit maakt het mogelijk om een lijst van objecten te genereren.

3.1.3 Build

Hiermee kun je specifieke waarden toekennen aan gegenereerde objecten.

3.1.4 Inject & Freeze

Met deze functies kun je ervoor zorgen dat bepaalde waarden vastgezet worden voor herhaald gebruik binnen je tests.

3.2 AutoFixture integreren in xUnit

3.2.1 AutoData

Injecteert automatisch gegenereerde objecten in je testen. Het is ook mogelijk om een waarde vast te zetten voor een bepaald type met behulp van het extra Frozen attribuut.

3.2.2 InlineAutoData

Combineert handmatig ingevoerde testdata met automatisch gegenereerde objecten.

3.2.3 Moq integreren in AutoFixture

Met de package AutoFixture.AutoMoq wordt het mogelijk om afhankelijkheden automatisch te mocken. Dit maakt van AutoFixture een auto-mocking container, waardoor je minder handmatig werk hoeft te verrichten om mocks op te zetten voor je testen.

3.2.4 AutoFixture, Moq en xUnit combineren

Door het combineren van AutoFixture, xUnit en Moq kun je testen schrijven die automatisch gegenereerde objecten, gesimuleerde afhankelijkheden (mocks) en de SUT (System Under Test) bevatten. Dit met behulp van de volgende twee custom attributen die nadien op elke test gebruikt kunnen worden.

Dit custom attribuut bevat enkel de customization om van AutoFixture een auto-mocking container te maken maar kan uitgebreid worden met alle nodige elementen die veelvuldig nodig zijn in je testen. Zo kan je hierin een in-memory database opzetten met Entity Framework, een vaste waarde geven aan een bepaald veld van een object, de mogelijkheden zijn eindeloos. Dit zorgt voor een aanzienlijke vermindering van het aantal boilerplate code. Hieronder kunnen we links een test zien zonder gebruik van de genoemde tools in deze blogpost. Rechts kunnen we zien hoe het aantal geschreven lijnen drastisch verminderd wanneer je er wel gebruik van maakt.

 

 

 

 

 

 

 

Geschreven door: Kevin V.