Wie kann ich überprüfen, ob eine bestimmte Methode nicht mit Mockito aufgerufen wurde?

625

Wie kann ich überprüfen, ob eine Methode nicht von der Abhängigkeit eines Objekts aufgerufen wird?

Zum Beispiel:

public interface Dependency {
    void someMethod();
}

public class Foo {
    public bar(final Dependency d) {
        ...
    }
}

Mit dem Foo-Test:

public class FooTest {
    @Test
    public void dependencyIsNotCalled() {
        final Foo foo = new Foo(...);
        final Dependency dependency = mock(Dependency.class);
        foo.bar(dependency);
        **// verify here that someMethod was not called??**
    }
}
Beluchin
quelle

Antworten:

1087

Noch aussagekräftiger:

import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;

// ...

verify(dependency, never()).someMethod();

Die Dokumentation dieser Funktion finden Sie in §4 "Überprüfen der genauen Anzahl der Aufrufe / mindestens x / nie" , und der neverJavadoc ist hier .

Brice
quelle
144
Die Verwendung neverist die beste und spezifischste Methode. Wenn Sie jedoch ein gesamtes Scheinobjekt überprüfen müssen, sollten Sie auch verifyZeroInteractions(mockObject)oder berücksichtigen verifyNoMoreInteractions(mockObject).
Jeff Bowman
Was tun, wenn someMethod privat ist?
Sumit Kumar Saha
1
Dann kann man es gar nicht erst verspotten (mit Mockito);) PowerMock erlaubt das, aber es ist komplexer einzurichten. Oder wenn Sie Eigentümer des Codes sind, lockern Sie die Sichtbarkeit des Pakets.
Brice
2
Seit 3.0.1 verifyZeroInteractionsist veraltet. verifyNoInteractions ist das eine alternative vorgeschlagen. Die Mockito-Version zum Zeitpunkt dieses Kommentars ist 3.3.3
VKB
108

Verwenden Sie das zweite Argument für die Mockito.verifyMethode wie folgt:

verify(dependency, Mockito.times(0)).someMethod()

Beluchin
quelle
11
public static VerificationMode never () {Rückgabezeiten (0); }
Gbero
3
never()ist nicht wesentlich lesbarer als times(0). Aber die Existenz von nevererhöht die kognitive Belastung und erschwert das Verständnis und die Erinnerung an die Verwendung des Mockito-Systems. Mockito hätte also nicht neverin die API aufgenommen werden sollen, es ist die mentalen Kosten nicht wert.
BT
Frage: Überprüft dieses Formular, ob someMethodes 0 Mal aufgerufen wurde, oder überprüft es nur, dass someMethodes nie mit Null-Argumenten aufgerufen wurde?
BT
@BT - Ich würde mir vorstellen, dass es überprüft, ob die someMethodArgumente mit Null null Mal aufgerufen wurden - nicht verifiziert.
Beluchin
18

Als allgemeineres Muster tendiere ich dazu, @Afterim Test einen Block zu verwenden :

@After
public void after() {
    verifyNoMoreInteractions(<your mock1>, <your mock2>...);
}

Dann ist der Test nur frei , um zu überprüfen , was sollte aufgerufen werden.

Außerdem stellte ich fest, dass ich oft vergessen hatte, nach "keine Interaktionen" zu suchen, um später festzustellen, dass Dinge aufgerufen wurden, die nicht hätten sein sollen.

Daher finde ich dieses Muster nützlich, um alle unerwarteten Anrufe abzufangen, die nicht speziell überprüft wurden.

David Lavender
quelle
9
In der Mockito-Dokumentation heißt es, dass dieses Muster nicht missbraucht werden sollte - "Ein Wort der Warnung: Einige Benutzer, die viele klassische Verspottungen mit erwarteter Ausführung und Überprüfung durchgeführt haben, verwenden sehr häufig verifyNoMoreInteractions (), selbst bei jeder Testmethode. VerifyNoMoreInteractions () wird nicht für jede Testmethode empfohlen. verifyNoMoreInteractions () ist eine praktische Aussage aus dem Interaktionstest-Toolkit. Verwenden Sie es nur, wenn es relevant ist. Missbrauch führt zu überbestimmten, weniger wartbaren Tests. " Siehe hier
Chadi
2
"Verwenden Sie es nur, wenn es relevant ist". Ich denke, dass es immer relevant ist. Ich sehe dieses Muster nicht als Missbrauch: Wie gesagt, es werden "Dinge genannt, die nicht hätten sein sollen". Für mich ist das eine wichtige Bestätigung: Wenn etwas ein Repository aufruft, das es nicht verwenden sollte, möchte ich es wissen! Es sei denn, es gibt eine andere Möglichkeit, dies zu überprüfen, ohne es zu verwenden verifyNoMoreInteractions? Die anderen Antworten hier beruhen darauf, dass der Testschreiber ausdrücklich daran denkt, diese Prüfungen aufzulisten: Das ist in meinem Buch zu fehleranfällig.
David Lavender
2
Ich habe diesen Kommentar gesehen, hatte aber auch das Gefühl, dass die Argumentation nicht zwingend war. Ich würde gerne mehr darüber lesen, warum dies nicht empfohlen wird.
Tobinibot
2
@tobinibot Weil die Idee des Unit-Tests darin besteht, einen Vertrag zu verifizieren. Bei den meisten Verträgen geht es normalerweise nicht darum, wie oft eine andere Methode aufgerufen wird, sondern darum, dass die Übergabe bekannter Parameter zu einer bekannten Antwort führt. Wenn Sie keine Interaktionen mehr verwenden, überprüfen Sie die Implementierung grundsätzlich Zeile für Zeile, was das Refactoring und die Implementierung mühsam macht. Welches ist nicht der Punkt der Unit-Tests.
Andrew T Finnell
8

Zuallererst: Sie sollten immer mockito static importieren, damit der Code viel besser lesbar (und intuitiver) ist:

import static org.mockito.Mockito.*;

Es gibt tatsächlich viele Möglichkeiten, dies zu erreichen, aber es ist (wohl) sauberer, das zu verwenden

verify(yourMock, times(0)).someMethod();

Methode für alle Tests, wenn Sie sie bei anderen Tests verwenden, um eine bestimmte Anzahl von Ausführungen wie folgt zu bestätigen:

verify(yourMock, times(5)).someMethod();

Alternativen sind:

verify(yourMock, never()).someMethod();

Alternativ - wenn Sie wirklich sicherstellen möchten, dass ein bestimmtes verspottetes Objekt überhaupt NICHT aufgerufen wird - können Sie Folgendes verwenden:

verifyZeroInteractions(yourMock)
fl0w
quelle
7

Sowohl die verifyNoMoreInteractions()als auch die verifyZeroInteractions()Methode haben intern dieselbe Implementierung wie:

public static transient void verifyNoMoreInteractions(Object mocks[])
{
    MOCKITO_CORE.verifyNoMoreInteractions(mocks);
}

public static transient void verifyZeroInteractions(Object mocks[])
{
    MOCKITO_CORE.verifyNoMoreInteractions(mocks);
}

Daher können wir eines davon für ein Scheinobjekt oder ein Array von Scheinobjekten verwenden, um zu überprüfen, ob keine Methoden mit Scheinobjekten aufgerufen wurden.

Ujjwal
quelle