TechTalk heeft voor SpecFlow natuurlijk al een handige set aan extensies uitgebracht die vooral het gebruik van eigen datatypes in combinatie met SpecFlow steps mogelijk maken. Dit is slimme, maar vrij geavanceerde set waarbij je best wel wat ervaring moet hebben met zowel het gebruik van SpecFlow als C#. De beginnende gebruiker zal eerder behoefte hebben om SpecFlow tables in meer simpele maar generieke types om te zetten als collecties. Die methoden worden niet standaard geleverd in de SpecFlow library, waarschijnlijk omdat ze als triviaal gezien worden door het ontwikkel team.
De .ToDictionary Extensie
Een van de fijnste data collections in C# is natuurlijk de Dictionary. Een key/value collectie waarbij de key uniek is. Daarom is het fijn om een verticale SpecFlow.Table om te kunnen zetten in een Dictionary. Hiervoor gebruiken we een extension method. Hiervoor maken we eerst een extension class:
Nu kunnen we onze eerste extension method aanmaken; een ToDictionary extension dat een SpecFlow Table omzet naar een dictionary:
Deze methode neemt van iedere rij uit een verticale SpecFlow tabel de eerste twee kolommen. De eerste kolom worden de key, de tweede kolom de value van de dictionary. We hadden dit natuurlijk ook in een one-line Linq expressie kunnen doen, maar dat gaat het doel van simpel en begrijpelijk voorbij.
Houdt er rekening mee dat als er foute waarden meegegeven worden, zoals een niet unieke key, de methode een standaard “An element with the same key already exists in the Dictionary<string, string>.” exceptie gooit.
Laten we hier een test voor schrijven om te controleren of het werkt:
En we maken de drie steps aan die erbij horen. In deze steps gebruiken we de extensie Table.ToDictionary() methode, de extensie die we net hebben aangemaakt. Mocht dit in eerste instantie niet werken: vergeet niet de library met de extensies te importeren.
Verder gebruiken we in deze drie steps het ScenarioContext.Current object om de Table en uiteindelijk de Dictionary door te geven tussen de steps. Het ScenarioContext.Current object is zelf ook een dictionary van het type <string, object>, je kan er dus elke type object ingooien wat je maar wilt. Als je een object terug wilt halen moet je wel aangeven wat voor type het is, “casten”, om alle methodes en properties van dit object weer te gebruiken. Dit zie je hieronder gebeuren met behulp van het type tussen haakjes:
var table = (Table)ScenarioContext.Current["table"]
En natuurlijk de proef op de som, het runnen van de test:
De .ToDataTable Extensie
Een ander prettig datatype voor als je meer data hebt, is de DataTable. Vergelijkbaar met de Dictionary, maar dan twee dimensionaal in plaats van een dimensionaal.
Hiervoor maken we een ToDataTable extensie op een vergelijkbare manier als we de ToDictionary extensie hebben gemaakt:
Deze methode verblijft in de TableExtension class, want het is een extensie op het SpecFlow.Table object.
Laten we er een test voor schrijven:
We recyclen de Given step, maar voor de When en Then steps moeten we twee steps aanmaken:
In deze steps gebruiken we zowel de Table.ToDictionary extensie als de nieuwe Table.ToDataTable extensie. In de Then step vergelijken we een Dictionary op overeenkomst met een DataTable.Row. Deze step gaat er wel vanuit dat de data welgevormd is. Als bijvoorbeeld een key uit de dictionary niet bestaat als column in de datatable krijg je een standaard exceptie toegeworpen.
Laten we de test uitvoeren:
Conclusie
Soms is het handig als je een SpecFlow.Table object kan omzetten naar een meer C# eigen object. Twee voor de hand liggende object typen zijn de Dictionary en de DataTable. Met behulp van extensions kan je makkelijk het Table object uitbreiden om te converteren naar een object naar keuze.
De code behorend bij deze exercitie vind je in blog: 'SpecFlow Extensies voor Dummies, de code'.
Comentários