gmock-instelling standaardacties / ON_CALL vs. EXPECT_CALL

Ik begrijp het verschil tussen ON_CALL en EXPECT_CALL niet als ik het gebruik om
specificeer de standaardactie.

Tot nu toe heb ik gemerkt/geleerd dat er twee manieren zijn om de standaardactie van een mock aan te passen:

ON_CALL(mock, methodX(_)).WillByDefault(Return(0x01));

of

EXPECT_CALL(mock, methodX(_)).WillRepeatedly(Return(0x01));

Kan iemand mij uitleggen:

  • Het verschil tussen de twee methoden
  • De ups en downs van elk
  • Wanneer is het gepast om ze te gebruiken (wat voor soort opstelling…)

Antwoord 1, autoriteit 100%

Er zijn subtiele maar significante verschillen tussen de twee uitspraken. EXPECT_CALLstelt verwachtingen bij een nep-oproep. Schrijven

EXPECT_CALL(mock, methodX(_)).WillRepeatedly(do_action);

vertelt gMock dat methodXeen willekeurig aantal keren op mockkan worden aangeroepen met welke argumenten dan ook, en als dat zo is, zal mockdo_action. Aan de andere kant,

ON_CALL(mock, methodX(_)).WillByDefault(do_action);

vertelt gMock dat wanneer methodXwordt aangeroepen op mock, het do_actionmoet uitvoeren. Die functie is handig in een scenario waarin je veel verwachtingen op je mock moet schrijven, en de meeste / allemaal dezelfde actie moeten specificeren – vooral als het complex is. Je kunt die actie specificeren in ON_CALL, en dan EXPECT_CALLs schrijven zonder de actie expliciet te specificeren. Bijvoorbeeld,

ON_CALL(mock, Sign(Eq(0), _))
  .WillByDefault(DoAll(SetArgPointee<1>("argument is zero"), Return(0)));
ON_CALL(mock, Sign(Gt(0), _))
  .WillByDefault(DoAll(SetArgPointee<1>("argument is positive"), Return(1)));
ON_CALL(mock, Sign(Lt(0), _))
  .WillByDefault(DoAll(SetArgPointee<1>("argument is negative"), Return(-1)));

Als je nu veel EXPECT_CALLs moet schrijven, hoef je niet elke keer mockhet gedrag te specificeren:

EXPECT_CALL(mock, Sign(-4, _));
EXPECT_CALL(mock, Sign(0, _));
EXPECT_CALL(mock, Sign(1, _)).Times(2);
EXPECT_CALL(mock, Sign(2, _));
EXPECT_CALL(mock, Sign(3, _));
EXPECT_CALL(mock, Sign(5, _));

In een ander voorbeeld, ervan uitgaande dat Sign intretourneert, als je schrijft

ON_CALL(mock, Sign(Gt(0), _)).WillByDefault(Return(1));
EXPECT_CALL(mock, Sign(10, _));

de aanroep mock.Sign(10)retourneert 1 omdat ON_CALLstandaardgedrag biedt voor een aanroep gespecificeerd door EXPECT_CALL. Maar als je schrijft

EXPECT_CALL(mock, Sign(Gt(0), _).WillRepeatedly(Return(1));
EXPECT_CALL(mock, Sign(10, _));

het aanroepen van mock.Sign(10, p)zal 0 opleveren. Het wordt vergeleken met de tweede verwachting. Die verwachting specificeert geen expliciete actie en gMock zal er een standaardactie voor genereren. Die standaardactie is het retourneren van een standaardwaarde van het retourtype, dat 0 is voor int. De eerste verwachting wordt in dit geval totaal genegeerd.


Antwoord 2, autoriteit 19%

ON_CALL(mock, methodX(_)).WillByDefault(Return(0x01));
EXPECT_CALL(mock, methodX(_)).WillRepeatedly(Return(0x01));

Zoals je al zei, doen deze twee lijnen precies hetzelfde, daarom zijn er helemaal geen verschillen. Gebruik beide manieren om een ​​standaardactie naar wens in te stellen.

Er is echter een logisch verschil:

  • ON_CALL(mock, methodX(_)).WillByDefault(Return(0x01));betekent dat de methode kan worden gebeld en als dat gebeurt, zal elke oproep 0x01
  • terugkeren

  • EXPECT_CALL(mock, methodX(_)).WillRepeatedly(Return(0x01));betekent dat er wordt verwacht dat de methode wordt gebeld en elke oproep zal 0x01
  • retourneren


Trouwens, er is een Standaard acties instellen in hun Cheat-vel, wat zegt:

Gebruik On_Call ():

om de standaardactie voor een bepaalde methode aan te passen.

ON_CALL(mock_object, method(matchers))
    .With(multi_argument_matcher)  ?
    .WillByDefault(action);

Antwoord 3, Autoriteit 6%

Hier is de “officiële” -uitleg over de belangrijkste verschillen tussen ON_CALLen EXPECT_CALLZoals uitgelegd in de Gmock Cookbook .

Er zijn eigenlijk twee constructies voor het definiëren van het gedrag van een schijnobject: ON_CALLEN EXPECT_CALL.

Het verschil?

ON_CALLBepaalt wat er gebeurt wanneer een schijnmethode wordt genoemd, maar houdt geen verwachting op de methode die wordt genoemd.

EXPECT_CALLBepaalt niet alleen het gedrag, maar stelt ook een verwachting in dat de methode met de opgegeven argumenten moet worden gebeld, voor het gegeven aantal keren (en in de opgegeven volgorde wanneer u Geef ook de bestelling op) .

Sinds EXPECT_CALLdoet meer, is het niet beter dan ON_CALL?

Niet echt. Elke EXPECT_CALLvoegt een beperking toe op het gedrag van de testcode. Meer beperkingen hebben dan noodzakelijk is slecht – nog erger dan niet genoeg beperkingen.

Dit kan tegen intuïtief zijn. Hoe kunnen testen die meer verifiëren zijn dan testen die minder verifiëren? Is niet verificatie het hele punt van tests?

Het antwoord, ligt in wat een test moet verifiëren. Een goede test verifieert het contract van de code. Als een test overmatig specificeert, laat het niet genoeg vrijheid aan de implementatie. Dientengevolge, het veranderen van de implementatie zonder het contract te verbreken (bijv. Refactoring en optimalisatie), wat prima zou moeten zijn, kan breken dergelijke tests. Dan moet je tijd doorbrengen met het oplossen ervan, alleen om ze opnieuw te zien de volgende keer dat de implementatie is gewijzigd.

Houd er rekening mee dat men niet meer dan één eigenschap in één test hoeft te verifiëren. In feite is het een goede stijl om slechts één ding in één test te verifiëren. Als je dat doet, zal een bug waarschijnlijk slechts één of twee tests breken in plaats van tientallen (welk geval zou je liever debuggen?). Als u ook in de gewoonte bent om tests te geven beschrijvende namen die vertellen wat ze verifiëren, kunt u vaak gemakkelijk raden wat er aan de hand is, net van het testlogboek zelf.

Dus gebruik het ON_CALLstandaard, en gebruik alleen EXPECT_CALLwanneer u eigenlijk wilt controleren of de oproep is gemaakt.


Antwoord 4

Zie hier https : //github.com/google/gooogletest/blob/master/docs/gmock_cook_book.md#knowing-when-to-expect-useoncall

Er zijn eigenlijk twee constructies voor het definiëren van het gedrag van een schijnobject: on_call en verwacht_call. Het verschil? On_call definieert wat er gebeurt wanneer een mock-methode wordt genoemd, maar houdt geen verwachting op de methode die wordt gebeld. EXPENT_CALL definieert niet alleen het gedrag, maar stelt ook een verwachting in dat de methode zal worden genoemd met de opgegeven argumenten, voor het gegeven aantal keren (en in de opgegeven volgorde wanneer u de bestelling ook opgeven).


Antwoord 5

Eén verschil is dat de ON_CALLGEDRAG (standaardgedrag) en de EXPECT_CALLVerwachtingen worden opgeruimd.

https ://github.com/google/googletest/blob/master/googlemock/docs/cheat_sheet.md#verifying-and-resetting-a-mock

using ::testing::Mock;
...
// Verifies and removes the expectations on mock_obj;
// returns true if and only if successful.
Mock::VerifyAndClearExpectations(&mock_obj);
...
// Verifies and removes the expectations on mock_obj;
// also removes the default actions set by ON_CALL();
// returns true if and only if successful.
Mock::VerifyAndClear(&mock_obj);

Dit kan worden gebruikt om de verwachtingen op een bepaald punt in uw test te wissen, maar toch het standaardgedrag van het nepobject te behouden. Merk op dat dit niet het geval is voor StrictMock-objecten, aangezien ze de test niet zullen laten slagen zonder daadwerkelijke verwachtingen, zelfs niet met een gedefinieerde standaardinstelling voor gedrag met ON_CALL.

Other episodes