wake-up-neo.net

Mockito - Spion gegen Spott

Mockito - Ich verstehe, dass ein Spion die echten Methoden für ein Objekt aufruft, während ein Mock Methoden für das Doppelobjekt aufruft. Spione sollten ebenfalls vermieden werden, es sei denn, es gibt einen Codegeruch. Wie funktionieren Spione jedoch und wann sollte ich sie tatsächlich einsetzen?

53
Abhinav

Technisch gesehen sind sowohl "Spott" als auch "Spion" eine besondere Art von "Test-Doubles".

Mockito macht den Unterschied leider komisch.

Ein Mock in mockito ist ein normaler Mock in anderen Mocking-Frameworks (ermöglicht das Stubben von Aufrufen; dh Rückgabe bestimmter Werte aus Methodenaufrufen).

Ein Spion in mockito ist ein partieller Schein in anderen spöttischen Frameworks (ein Teil des Objekts wird verspottet und ein Teil verwendet echte Methodenaufrufe).

60

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

Ich kopiere etwas davon 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 brauchen Sie keinen Spion, weil Sie einfach nur DepositMoneyService und WithdrawMoneyService verspotten können.

Aber mit etwas altem Code liegt 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 die API wird geändert. Wenn diese Methode von vielen Orten verwendet 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 kannst du den Spion benutzen, 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.

11

TL; DR-Version,

Mit mock erstellt es eine reine Shell-Instanz für Sie.

List<String> mockList = Mockito.mock(ArrayList.class);

Mit Spion können Sie teilweise auf eine bestehende Instanz spekulieren

List<String> spyList = Mockito.spy(new ArrayList<String>());

Typischer Anwendungsfall für Spy: Die Klasse verfügt über einen parametrisierten Konstruktor. Zuerst möchten Sie das Objekt erstellen.

9
del bao

Der beste Startpunkt ist wahrscheinlich die Dokumente für Mockito .

Generell können Sie mit dem Mockito-Mock Stubs erstellen. 

Sie würden eine Stub-Methode erstellen, wenn diese Methode beispielsweise einen teuren Vorgang ausführt. Angenommen, es erhält eine Datenbankverbindung, ruft einen Wert aus der Datenbank ab und gibt ihn an den Aufrufer zurück. Das Abrufen der Datenbankverbindung kann 30 Sekunden dauern, wodurch die Testausführung auf den Punkt verlangsamt wird, an dem Sie wahrscheinlich den Kontext wechseln (oder den Test beenden). 

Wenn sich die von Ihnen getestete Logik nicht für die Datenbankverbindung interessiert, können Sie diese Methode durch einen Stub ersetzen, der einen hartcodierten Wert zurückgibt.

Mit dem Mockito-Spion können Sie überprüfen, ob eine Methode andere Methoden aufruft. Dies kann sehr nützlich sein, wenn Sie versuchen, Legacy-Code zu testen.

Es ist nützlich, wenn Sie eine Methode testen, die Nebenwirkungen durchläuft, dann würden Sie einen Mockito-Spion verwenden. Dadurch werden Aufrufe an das reale Objekt delegiert, und Sie können den Methodenaufruf, die Häufigkeit des Aufrufs usw. überprüfen.

9

Beide können zum Nachahmen von Methoden oder Feldern verwendet werden. Der Unterschied ist, dass Sie in einem Schein einen kompletten Schein oder ein falsches Objekt erstellen, während Sie in einem Spion das eigentliche Objekt finden und Sie nur bestimmte Methoden davon ausspähen oder stupfen.

Während es sich bei Spionageobjekten natürlich um eine echte Methode handelt, wird die Methode wirklich aufgerufen, wenn Sie die Methode nicht stummeln. Wenn Sie die Methode ändern und simulieren möchten, müssen Sie sie stubben.

Betrachten Sie das folgende Beispiel als Vergleich.

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Spy;
import org.mockito.runners.MockitoJUnitRunner;
 
import Java.util.ArrayList;
import Java.util.List;
 
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.when;
 
@RunWith(MockitoJUnitRunner.class)
public class MockSpy {
 
    @Mock
    private List<String> mockList;
 
    @Spy
    private List<String> spyList = new ArrayList();
 
    @Test
    public void testMockList() {
        //by default, calling the methods of mock object will do nothing
        mockList.add("test");

        Mockito.verify(mockList).add("test");
        assertEquals(0, mockList.size());
        assertNull(mockList.get(0));
    }
 
    @Test
    public void testSpyList() {
        //spy object will call the real method when not stub
        spyList.add("test");

        Mockito.verify(spyList).add("test");
        assertEquals(1, spyList.size());
        assertEquals("test", spyList.get(0));
    }
 
    @Test
    public void testMockWithStub() {
        //try stubbing a method
        String expected = "Mock 100";
        when(mockList.get(100)).thenReturn(expected);
 
        assertEquals(expected, mockList.get(100));
    }
 
    @Test
    public void testSpyWithStub() {
        //stubbing a spy method will result the same as the mock object
        String expected = "Spy 100";
        //take note of using doReturn instead of when
        doReturn(expected).when(spyList).get(100);
 
        assertEquals(expected, spyList.get(100));
    }
}

Wann sollten Sie Schein oder Spion benutzen? Wenn Sie sicher sein möchten, externe Dienste nicht anrufen und nur die Logik im Gerät testen möchten, verwenden Sie Mock. Wenn Sie einen externen Dienst aufrufen und eine echte Abhängigkeit aufrufen möchten, oder einfach nur sagen möchten, dass Sie das Programm so ausführen möchten, wie es ist, und nur bestimmte Methoden stubben, dann verwenden Sie spy. Das ist also der Unterschied zwischen Spion und Spott in Mockito.

8
Vu Truong

Ich mag die Einfachheit dieser Empfehlung:

  • Wenn Sie sicher sein möchten, externe Dienste nicht anrufen und nur die Logik im Gerät testen möchten, verwenden Sie mock.
  • Wenn Sie einen externen Dienst aufrufen und echte Abhängigkeiten aufrufen möchten, oder einfach nur sagen möchten, dass Sie das Programm so ausführen möchten, wie es ist, und nur bestimmte Methoden stubben, verwenden Sie spy.

Quelle: https://javapointers.com/tutorial/difference-between-spy-and-mock-in-mockito/

1
leo9r

Sie können der folgenden Blog-URL folgen, in der sie mit den folgenden Punkten verglichen wird:

  1. Objektdeklaration
  2. Wenn die Methoden nicht verspottet werden
  3. Wenn die Methode verspottet wird

https://onlyfullstack.blogspot.com/2019/02/mockito-mock-vs-spy.html URL des Haupttutorials - https://onlyfullstack.blogspot.com/2019/02/mockito-tutorial .html

0
Saurabh Oza