GoogleMock: Controleren of een methode is aangeroepen
Inleiding tot googlemock
Deze handleiding behandelt een veelvoorkomend probleem bij het unit testen met **GoogleMock**: hoe te controleren of een methode van een klasse is aangeroepen vanuit een andere methode binnen dezelfde klasse. Het doel is om de methode Foo::runMe() aan te roepen op een object en te verifiëren of de methode Foo::mockMe() van hetzelfde object is aangeroepen met specifieke parameters. We willen dus Foo::runMe() uitvoeren en de verwachtingen over de aanroep van Foo::mockMe() controleren.
De originele en mock klasse
De basisstructuur van de klassen ziet er als volgt uit: een abstracte klasse Foo met virtuele methoden runMe() en mockMe(). Vervolgens een mock klasse MockFoo die van Foo erft en de **GoogleMock** macro's MOCK_METHOD0 en MOCK_METHOD1 gebruikt om de methoden te mocken. Het is belangrijk te begrijpen dat een mock object standaard de gemockte methoden niet implementeert, waardoor een aanroep direct faalt.
Het probleem met standaard mocking
Wanneer je een MockFoo object aanmaakt en runMe() aanroept, zal de methode niet worden uitgevoerd omdat deze gemocked is. Als je een verwachting stelt dat mockMe() wordt aangeroepen, zal de test falen. Dit komt doordat de mock methode niet de daadwerkelijke implementatie van runMe() uitvoert. De test TEST_F(FooTest, runMeCallsMockMeWithTrue) demonstreert dit probleem en laat zien hoe de test faalt.
De oplossing: een 'realrunme()' methode
De oplossing is om een extra methode toe te voegen aan MockFoo die de virtuele methode runMe() van de parent klasse aanroept. Deze methode, realRunMe(), zorgt ervoor dat de daadwerkelijke implementatie van Foo::runMe() wordt uitgevoerd. Door realRunMe() aan te roepen in de test, wordt Foo::runMe() aangeroepen, wat vervolgens de virtuele methode mockMe() op het MockFoo object aanroept, waardoor de verwachtingen kunnen worden geverifieerd.
Alternatieve oplossing: on_call
Een alternatieve aanpak zou kunnen zijn om een methode te creëren die ON_CALL aanroepen gebruikt om de mock te configureren. Echter, deze methode zou nog steeds binnen de MockFoo klasse moeten worden geïmplementeerd om toegang te hebben tot het parent Foo object. De overhead lijkt vergelijkbaar, maar de oplossing met realRunMe() wordt als meer direct en overzichtelijk beschouwd.
Conclusie en beste praktijken
Het gebruik van een realRunMe() methode in de **MockFoo** klasse is een effectieve manier om te controleren of een methode is aangeroepen vanuit een andere methode binnen dezelfde klasse bij het unit testen met **GoogleMock**. Deze aanpak biedt een duidelijke en eenvoudige oplossing voor het verifiëren van aanroepen en verwachtingen in je tests. Overweeg deze techniek wanneer je complexe interacties tussen methoden binnen een klasse wilt testen.
