it-swarm.com.de

Was ist der Unterschied zwischen Verspotten und Ausspähen bei der Verwendung von Mockito?

Was wäre ein Anwendungsfall für die Verwendung eines Mockito-Spions?

Es scheint mir, dass jeder Spionage-Anwendungsfall mit callRealMethod mit einem Mock behandelt werden kann.

Ein Unterschied, den ich sehen kann, ist, wenn Sie möchten, dass die meisten Methodenaufrufe real sind, werden einige Codezeilen eingespart, um einen Schein oder einen Spion zu verwenden. Ist es das oder vermisse ich das größere Bild?

125
Victor Grazi

Die Antwort ist in die Dokumentation :

Echte Teilverspottungen (seit 1.8.0)

Nach vielen internen Debatten und Diskussionen auf der Mailingliste wurde Mockito schließlich um eine teilweise Scheinunterstützung erweitert. Bisher haben wir partielle Mocks als Code-Gerüche betrachtet. Wir haben jedoch einen legitimen Anwendungsfall für Teilverspottungen gefunden.

Vor der Veröffentlichung von 1.8 produzierte spy () keine echten Teil-Mocks und es war für einige Benutzer verwirrend. Lesen Sie mehr über das Ausspionieren: hier oder in der javadoc for spy (Object) -Methode.

callRealMethod() wurde nach spy() eingeführt, aber spy () wurde natürlich dort gelassen, um die Abwärtskompatibilität sicherzustellen.

Ansonsten haben Sie Recht: Alle Methoden eines Spions sind real, es sei denn, sie sind abgestumpft. Alle Methoden eines Mocks werden abgebrochen, es sei denn, callRealMethod() wird aufgerufen. Im Allgemeinen würde ich es vorziehen, callRealMethod() zu verwenden, da es mich nicht zwingt, die doXxx().when()-Redewendung anstelle der traditionellen when().thenXxx() zu verwenden.

90
JB Nizet

Unterschied zwischen einem Spion und einem Mock

Wenn Mockito einen Mock erstellt, geschieht dies aus der Klasse eines Typs und nicht aus einer tatsächlichen Instanz. Der Mock erstellt einfach eine reine Shell-Instanz der Klasse, die vollständig instrumentiert ist, um Interaktionen mit ihr zu verfolgen. Auf der anderen Seite wird der Spion eine vorhandene Instanz einwickeln. Es verhält sich immer noch so wie in der normalen Instanz - der einzige Unterschied besteht darin, dass es auch instrumentiert wird, um alle Interaktionen mit ihm zu verfolgen.

Im folgenden Beispiel erstellen wir einen Mock der ArrayList-Klasse:

@Test
public void whenCreateMock_thenCreated() {
    List mockedList = Mockito.mock(ArrayList.class);

    mockedList.add("one");
    Mockito.verify(mockedList).add("one");

    assertEquals(0, mockedList.size());
}

Wie Sie sehen, fügt das Hinzufügen eines Elements zur verspotteten Liste eigentlich nichts hinzu, sondern ruft die Methode ohne weitere Nebenwirkungen auf. Ein Spion hingegen verhält sich anders - er ruft die eigentliche Implementierung der add-Methode auf und fügt das Element der zugrunde liegenden Liste hinzu:

@Test
public void whenCreateSpy_thenCreate() {
    List spyList = Mockito.spy(new ArrayList());
    spyList.add("one");
    Mockito.verify(spyList).add("one");

    assertEquals(1, spyList.size());
}

Hier können wir mit Sicherheit sagen, dass die reale interne Methode des Objekts aufgerufen wurde, denn wenn Sie die size () -Methode aufrufen, erhalten Sie die Größe 1, aber diese size () -Methode wurde nicht verspottet! Woher kommt also 1? Die interne Methode size () wird aufgerufen, da size () nicht verspottet (oder gestubbt) ist, und daher können wir Sagen Sie, dass der Eintrag zum realen Objekt hinzugefügt wurde.

Quelle: http://www.baeldung.com/mockito-spy + Eigennotizen.

75
Saurabh Patil

Wenn es ein Objekt mit 8 Methoden gibt und Sie einen Test haben, bei dem Sie 7 reale Methoden aufrufen und eine Methode entfernen möchten, haben Sie zwei Möglichkeiten:

  1. Wenn Sie einen Mock verwenden, müssen Sie ihn einrichten, indem Sie 7 callRealMethod aufrufen und eine Methode stubben
  2. Mit einem spy müssen Sie es einrichten, indem Sie eine Methode stubben

Die offizielle Dokumentation auf doCallRealMethod empfiehlt die Verwendung eines Spions für Teilverspottungen.

Siehe auch javadoc spy (Object), um mehr über partielle Mocks zu erfahren. Mockito.spy () ist eine empfohlene Methode zum Erstellen partieller Mocks. Der Grund dafür ist, dass echte Methoden für korrekt erstellte Objekte aufgerufen werden, da Sie für die Erstellung des an die spy () -Methode übergebenen Objekts verantwortlich sind.

33
user2412398

Spy kann nützlich sein, wenn Sie Komponententests für Legacy-Code erstellen möchten.

Ich habe hier ein lauffähiges Beispiel erstellt https://www.surasint.com/mockito-with-spy/ , einige davon kopiere ich hier.

Wenn Sie so etwas wie diesen Code haben:

public void transfer(  DepositMoneyService depositMoneyService, WithdrawMoneyService withdrawMoneyService, 
             double amount, String fromAccount, String toAccount){
    withdrawMoneyService.withdraw(fromAccount,amount);
    depositMoneyService.deposit(toAccount,amount);
}

Möglicherweise benötigen Sie keinen Spion, da Sie DepositMoneyService und WithdrawMoneyService nur verspotten können.

Bei einigen älteren Codes ist die Abhängigkeit im Code wie folgt:

    public void transfer(String fromAccount, String toAccount, double amount){

        this.depositeMoneyService = new DepositMoneyService();
        this.withdrawMoneyService = new WithdrawMoneyService();

        withdrawMoneyService.withdraw(fromAccount,amount);
        depositeMoneyService.deposit(toAccount,amount);
    }

Ja, Sie können zum ersten Code wechseln, aber dann wird die API geändert. Wenn diese Methode an vielen Orten angewendet wird, müssen Sie alle ändern.

Alternativ können Sie die Abhängigkeit folgendermaßen extrahieren:

    public void transfer(String fromAccount, String toAccount, double amount){
        this.depositeMoneyService = proxyDepositMoneyServiceCreator();
        this.withdrawMoneyService = proxyWithdrawMoneyServiceCreator();

        withdrawMoneyService.withdraw(fromAccount,amount);
        depositeMoneyService.deposit(toAccount,amount);
    }
    DepositMoneyService proxyDepositMoneyServiceCreator() {
        return new DepositMoneyService();
    }

    WithdrawMoneyService proxyWithdrawMoneyServiceCreator() {
        return new WithdrawMoneyService();
    }

Dann können Sie den Spion verwenden, um die Abhängigkeit wie folgt zu injizieren:

DepositMoneyService mockDepositMoneyService = mock(DepositMoneyService.class);
        WithdrawMoneyService mockWithdrawMoneyService = mock(WithdrawMoneyService.class);

    TransferMoneyService target = spy(new TransferMoneyService());

    doReturn(mockDepositMoneyService)
            .when(target).proxyDepositMoneyServiceCreator();

    doReturn(mockWithdrawMoneyService)
            .when(target).proxyWithdrawMoneyServiceCreator();

Weitere Details im obigen Link.

4