Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien

Shims gebruiken voor het testen van je eigen code

Pagina: 1
Acties:

  • Jan_V
  • Registratie: Maart 2002
  • Laatst online: 21-11 21:28
Momenteel zit ik op een project waar we veelvuldig gebruik maken van het Fakes Framework van Microsoft. Een van de features van dit framework is het maken van shims. Dit stelt je in staat om een soort van stubs/mocks te maken voor classes die public/sealed/non-overridable zijn. Een veel gebruikt voorbeeld is DateTime.Now. Enorm handig voor het testen van framework klassen waar je geen controle over hebt.

Nu gebruiken we het fakes framework op dit project ook veel voor het shimmen van onze eigen klassen. Deze klassen hebben dus wel public/internal methodes, maar geen interface, virtual en/of abstracte methodes. Veelal zijn dit factories, builders, filters, maar ook vele andere type klassen.
Zelf vind ik het gebruik van shims veel weg hebben van TDD cheating. Je code is immers niet testbaar opgezet en daardoor moet je ineens gebruik maken van dit soort technieken.

Het voordeel is natuurlijk dat je niet 'onnodige' interfaces hoeft te definieren die alleen maar bestaan om je code testbaar te maken. Of nog erger, allemaal abstracte en virtual methodes/klassen te maken, alleen maar om dit te kunnen mocken/stubben. Je vervuilt je codebase dus niet om het beter testbaar te maken.

Aangezien ik natuurlijk niet de enige ben die in grote en complexe projecten meedraai vroeg ik me af hoe dit in jullie projecten wordt aangepakt. Ook vraag ik me af of ik de enige ben die shims een enigzins smerig vind, of dat die mening ook hier wordt gedeeld.

Battle.net - Jandev#2601 / XBOX: VriesDeJ


  • johnkeates
  • Registratie: Februari 2008
  • Laatst online: 04-07 16:30
Ook ik vind shims smerig. Liever interfaces die bestaan om je TDD proces te ondersteunen dan dat.

Daarnaast is het vaak ook nog wel prettig als je voor je tests zelf wat meer controle over je mocks/stubs hebt, ook al betekent dat iets meer werk. Dat is ook een beetje het probleem met het semi-automatisch creëren van dit soort dingen; het zijn bijna geen zinvolle tests meer, gezien je ze net zo goed on-the-fly in je test suite mee kan nemen zonder ze per class te creëren.

  • Herko_ter_Horst
  • Registratie: November 2002
  • Niet online
Als je het hebt over "het shimmen van onze eigen klassen", bedoel je dan de code-under-test of andere code die toevallig ook van jullie is?

"Any sufficiently advanced technology is indistinguishable from magic."


  • Jan_V
  • Registratie: Maart 2002
  • Laatst online: 21-11 21:28
Herko_ter_Horst schreef op donderdag 10 juli 2014 @ 16:38:
Als je het hebt over "het shimmen van onze eigen klassen", bedoel je dan de code-under-test of andere code die toevallig ook van jullie is?
De code-under-test uiteraard niet.
Echter gebruikt de code-under-test ook vaak andere klassen. Veelal worden deze door middel van interfaces ontsloten en met je IoC/DI framework geinjecteerd.
Maar het komt ook voor dat je gebruik maakt van klassen die dus geen interface (of iets dergelijks) hebben en dus gebruik maken van een concrete klasse, welke dus niet te testen is (via mocks of stubs). De code-under-test is dus tightly-coupled aan deze externe concrete klasse (welke dus elders in onze code leeft). Je wilt deze externe klasse natuurlijk niet testen in de unit test, aangezien het prima mogelijk is dat deze langdurende operaties doet.
M'n gevoel zegt dat je hier eigenlijk een interface of iets dergelijks voor wilt gebruiken, maar het maken van interfaces die alleen dienen voor het testen van je code is natuurlijk ook vervuiling. Persoonlijk vind ik dat interfaces, abstracte klassen en virtuele methoden ook een doel moeten hebben en dat doel moet niet 'testen' zijn.

Battle.net - Jandev#2601 / XBOX: VriesDeJ


  • HMS
  • Registratie: Januari 2004
  • Laatst online: 17-11 00:33

HMS

Ik modeleer meestal het aanroep van DateTime.Now (liever nog UtcNow) als het lezen van een klok. Dus dan heeft die code een dependency op IClock of ISystemClock. Die kan je dan in je unit tests vervangen door een mock, hierdoor kan je je unit test dus erg goed isoleren. Als je daarnaast ook alleen assertions doet op geaccepteerde input en waarneembare effecten van de unit, dan ben je al een heel eind.

Je kan je trouwens ook afvragen hoe betrouwbaar je unit tests zijn als ze zich niet beperken tot de unit, maar ook alle concrete dependencies. Een bug in 1 component kan dan een hele zooi unit tests omgooien.