Jak sprawdzić, czy konkretna metoda nie została wywołana za pomocą Mockito?

625

Jak sprawdzić, czy metoda nie jest wywoływana w zależności od obiektu?

Na przykład:

public interface Dependency {
    void someMethod();
}

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

Dzięki testowi Foo:

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
źródło

Odpowiedzi:

1087

Jeszcze bardziej znaczący:

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

// ...

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

Dokumentacja tej funkcji znajduje się w §4 „Weryfikacja dokładnej liczby wywołań / przynajmniej x / nigdy” , a neverjavadoc jest tutaj .

Brice
źródło
144
Używanie neverjest najlepszym i najbardziej konkretnym sposobem, ale jeśli chcesz sprawdzić cały próbny obiekt, rozważ również verifyZeroInteractions(mockObject)lub verifyNoMoreInteractions(mockObject).
Jeff Bowman
co zrobić, jeśli someMethod jest prywatny?
Sumit Kumar Saha
1
Wtedy nie możesz wyśmiewać go w pierwszej kolejności (za pomocą Mockito);) PowerMock pozwala na to, ale jego konfiguracja jest bardziej skomplikowana. Lub jeśli masz prawo do kodu, zmniejszasz widoczność pakietu.
Brice
2
Od 3.0.1 verifyZeroInteractionsjest przestarzałe. verifyNoInteractions jest sugerowaną alternatywą. Wersja Mockito w momencie komentarza to 3.3.3
VKB
108

użyj drugiego argumentu Mockito.verifymetody, jak w:

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

Beluchin
źródło
11
public static VerificationMode never () {czasy powrotu (0); }
gbero,
3
never()nie jest znacznie bardziej czytelny niż times(0). Ale istnienie neverzwiększa obciążenie poznawcze i sprawia, że ​​system mockito jest trudniejszy do zrozumienia i zapamiętania, jak go używać. Tak naprawdę mockito nie powinno było być zawarte neverw ich API, nie jest to warte kosztu psychicznego.
BT
Pytanie: czy ten formularz weryfikuje, że someMethodzostał wywołany 0 razy, czy tylko sprawdza, czy someMethodnigdy nie został wywołany z zerowymi argumentami?
BT
@BT - Wyobrażam sobie, że weryfikuje, że someMethodz zerowymi argumentami nazywano zero razy - niezweryfikowane.
beluchin 15.01.19
18

Jako bardziej ogólny wzorzec do naśladowania, zwykle używam @Afterbloku w teście:

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

Następnie test może zweryfikować tylko to, co należy nazwać.

Odkryłem również, że często zapominałem sprawdzać „brak interakcji”, ale później odkryłem, że nazywane są rzeczy, które nie powinny były być.

Uważam więc, że ten wzór jest przydatny do przechwytywania wszystkich nieoczekiwanych połączeń, które nie zostały specjalnie zweryfikowane.

David Lavender
źródło
9
Dokumentacja Mockito mówi, że nie należy nadużywać tego wzorca - „Słowo ostrzeżenia: niektórzy użytkownicy, którzy wykonali wiele klasycznych prób kpiny typu„ oczekuj i uruchom-weryfikuj ”, często używają VerifyNoMoreInteractions (), nawet w każdej metodzie testowej. () nie jest zalecane do użycia w każdej metodzie testowej. VerifiedNoMoreInteractions () jest przydatnym stwierdzeniem z zestawu narzędzi do testowania interakcji. Używaj go tylko wtedy, gdy jest to istotne. Nadużywanie go prowadzi do nadmiernie określonych, mniej konserwowalnych testów. ” Zobacz tutaj
Chadi
2
„Używaj go tylko wtedy, gdy jest to istotne”. Uważam, że jest to zawsze istotne. Nie widzę tego wzoru jako nadużycia: jak powiedziałem, stwierdza, że ​​„nazywano rzeczy, które nie powinny były być”. Dla mnie jest to istotny element weryfikacji: jeśli coś wywołuje repozytorium, z którego nie powinno korzystać, chcę o tym wiedzieć! Chyba że istnieje inny sposób na sprawdzenie tego bez użycia verifyNoMoreInteractions? Inne odpowiedzi tutaj polegają na pisarzu testów, który wyraźnie pamięta, aby wymienić te kontrole: to zbyt podatne na błędy w mojej książce.
David Lavender
2
Widziałem ten komentarz, ale czułem też, że rozumowanie nie jest przekonujące. Chciałbym przeczytać więcej o tym, dlaczego nie jest to zalecane.
tobinibot,
2
@tobinibot Ponieważ celem testów jednostkowych jest weryfikacja kontraktu. Większość umów zazwyczaj nie wiąże się z tym, ile razy przywoływana jest inna metoda, ale raczej przekazanie znanych parametrów skutkuje znaną odpowiedzią. Nie używając więcej interakcji, zasadniczo weryfikujesz implementację linia po linii, co sprawia, że ​​refaktoryzacja i implementacja są uciążliwe. Co nie jest celem testów jednostkowych.
Andrew T Finnell,
8

Po pierwsze: zawsze powinieneś importować mockito static, w ten sposób kod będzie znacznie bardziej czytelny (i intuicyjny):

import static org.mockito.Mockito.*;

Istnieje wiele sposobów na osiągnięcie tego, jednak korzystanie z niego jest (prawdopodobnie) czystsze

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

w całym teście, podczas innych testów używasz go do potwierdzenia pewnej liczby wykonań takich jak to:

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

Alternatywami są:

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

Alternatywnie - jeśli naprawdę chcesz się upewnić, że pewien wyśmiewany Obiekt wcale NIE jest wywoływany - możesz użyć:

verifyZeroInteractions(yourMock)
fl0w
źródło
7

Zarówno metoda, jak verifyNoMoreInteractions()i verifyZeroInteractions()metoda wewnętrznie mają taką samą implementację jak:

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

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

więc możemy użyć dowolnego z nich na próbnym obiekcie lub tablicy próbnych obiektów, aby sprawdzić, czy żadne metody nie zostały wywołane przy użyciu fałszywych obiektów.

Ujjwal
źródło