Come verificare che un metodo specifico non sia stato chiamato utilizzando Mockito?


626

Come verificare che un metodo non sia chiamato sulla dipendenza di un oggetto?

Per esempio:

public interface Dependency {
    void someMethod();
}

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

Con il test 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??**
    }
}

Risposte:


1088

Ancora più significativo:

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

// ...

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

La documentazione di questa funzione è disponibile §4 "Verifica del numero esatto di invocazioni / almeno x / mai" , e il neverjavadoc è qui .


144
L'uso neverè il modo migliore e più specifico, ma se è necessario controllare un intero oggetto simulato, considerare anche verifyZeroInteractions(mockObject)o verifyNoMoreInteractions(mockObject).
Jeff Bowman,

cosa fare se someMethod è privato ??
Sumit Kumar Saha,

1
Quindi non puoi deriderlo in primo luogo (con Mockito);) PowerMock lo consente, ma è più complesso da configurare. O se possiedi il codice, rilassi la visibilità del pacchetto.
Brice,

2
Da 3.0.1 verifyZeroInteractionsè stato deprecato. verifyNoInteractions è l'alternativa suggerita. La versione di Mockito al momento di questo commento è 3.3.3
VKB

108

usa il secondo argomento sul Mockito.verifymetodo, come in:

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


11
public stat VerificationMode never () {tempi di ritorno (0); }
gbero,

3
never()non è significativamente più leggibile di times(0). Ma l'esistenza di neveraumenta il carico cognitivo e rende il sistema mockito più difficile da capire e ricordare come usare. Quindi davvero mockito non avrebbe dovuto essere incluso nevernella loro API, non vale il costo mentale.
BT,

Domanda: questo modulo verifica che sia someMethodstato chiamato 0 volte o verifica solo che someMethodnon sia mai stato chiamato con zero argomenti?
BT,

@BT - Immagino che verifica che someMethodcon zero argomenti sia stato chiamato zero volte - non verificato.
Beluchin,

18

Come modello più generale da seguire, tendo a usare un @Afterblocco nel test:

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

Quindi il test è gratuito per verificare solo ciò che dovrebbe essere chiamato.

Inoltre, ho scoperto che spesso mi ero dimenticato di controllare "nessuna interazione", solo per scoprire in seguito che le cose venivano chiamate che non avrebbero dovuto essere.

Quindi trovo questo schema utile per intercettare tutte le chiamate impreviste che non sono state specificamente verificate.


9
La documentazione di Mockito afferma che questo modello non dovrebbe essere abusato - "Un avvertimento: alcuni utenti che hanno fatto un sacco di beffe classiche, si aspettano di eseguire la verifica tendono ad usare molto spesso verificaNoMoreInteractions (), anche in tutti i metodi di prova. () non è consigliabile utilizzare in tutti i metodi di test. confirmNoMoreInteractions () è un'affermazione utile dal toolkit di test di interazione. Utilizzalo solo quando è pertinente. L'abuso porta a test troppo specificati e meno gestibili. " Vedi qui
Chadi

2
"Usalo solo quando è rilevante". Sento che è sempre rilevante. Non vedo questo schema come un abuso: come ho detto, trova "le cose venivano chiamate che non avrebbero dovuto essere". Per me è una verifica fondamentale: se qualcosa sta chiamando un repository che non dovrebbe usare, voglio saperlo! A meno che non ci sia un altro modo per verificarlo senza usare verifyNoMoreInteractions? Le altre risposte qui si basano sul test writer che ricorda esplicitamente di elencare questi controlli: questo è troppo soggetto a errori nel mio libro.
David Lavender,

2
Ho visto questo commento, ma ho anche pensato che il ragionamento non fosse convincente. Mi piacerebbe leggere di più sul perché questo non è raccomandato.
Tobinibot,

2
@tobinibot Perché l'idea del test unitario è verificare un contratto. La maggior parte dei contratti non implica in genere quante volte viene invocato un altro metodo, ma piuttosto il passaggio di parametri noti comporta una risposta nota. Non usando più interazioni, sostanzialmente si verifica l'implementazione riga per riga, il che rende noioso il refactoring e l'implementazione. Non è questo il punto del test unitario.
Andrew T Finnell,

8

Prima di tutto: dovresti sempre importare mockito static, in questo modo il codice sarà molto più leggibile (e intuitivo):

import static org.mockito.Mockito.*;

In realtà ci sono molti modi per raggiungere questo obiettivo, tuttavia è (probabilmente) più pulito usare

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

metodo su tutti i test, quando su altri test lo usi per affermare un certo numero di esecuzioni come questa:

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

Le alternative sono:

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

In alternativa - quando vuoi davvero assicurarti che un certo Oggetto deriso NON sia effettivamente chiamato affatto - puoi usare:

verifyZeroInteractions(yourMock)

7

Sia la verifyNoMoreInteractions()e verifyZeroInteractions()metodo hanno internamente la stessa implementazione come:

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

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

così possiamo usarne uno qualsiasi su un oggetto finto o su una matrice di oggetti finti per verificare che nessun metodo sia stato chiamato usando oggetti finti.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.