Mockito - Usare le spie

1. Panoramica

In questo tutorial, illustreremo come ottenere il massimo dalle spie in Mockito .

Parleremo della @Spy annotazione, come stub una spia e, infine, - andremo nella differenza tra Mock e Spy .

E, naturalmente, per più bontà di Mockito, dai un'occhiata alla serie qui.

2. Semplice esempio di spia

Cominciamo con un semplice esempio di come utilizzare una spia .

In poche parole, l'API è Mockito.spy () - per spiare un oggetto reale .

Questo ci consentirà di chiamare tutti i normali metodi dell'oggetto tenendo traccia di ogni interazione, proprio come faremmo con una simulazione.

OK, facciamo un rapido esempio in cui spiare un oggetto ArrayList esistente :

@Test public void whenSpyingOnList_thenCorrect() { List list = new ArrayList(); List spyList = Mockito.spy(list); spyList.add("one"); spyList.add("two"); Mockito.verify(spyList).add("one"); Mockito.verify(spyList).add("two"); assertEquals(2, spyList.size()); }

Nota come viene effettivamente chiamato il metodo reale add () e come la dimensione di spyList diventa 2.

3. L' annotazione @Spy

Avanti: vediamo come utilizzare l' annotazione @Spy . Possiamo usare l' annotazione @Spy invece di spy () come nell'esempio seguente:

@Spy List spyList = new ArrayList(); @Test public void whenUsingTheSpyAnnotation_thenObjectIsSpied() { spyList.add("one"); spyList.add("two"); Mockito.verify(spyList).add("one"); Mockito.verify(spyList).add("two"); assertEquals(2, spyList.size()); }

Per abilitare l'annotazione Mockito (come @Spy , @Mock , ...), dobbiamo eseguire una delle seguenti operazioni:

  • Chiama il metodo MockitoAnnotations.initMocks (this) per inizializzare i campi annotati
  • Usa il runner integrato @RunWith (MockitoJUnitRunner.class)

4. Stubbing una spia

Ora, vediamo come spegnere una spia . Possiamo configurare / sovrascrivere il comportamento di un metodo usando la stessa sintassi che useremmo con un mock.

Nel seguente esempio, usiamo doReturn () per sovrascrivere il metodo size () :

@Test public void whenStubASpy_thenStubbed() { List list = new ArrayList(); List spyList = Mockito.spy(list); assertEquals(0, spyList.size()); Mockito.doReturn(100).when(spyList).size(); assertEquals(100, spyList.size()); }

5. Mock vs Spy in Mockito

Ora - discutiamo la differenza tra Mock e Spy in Mockito - non le differenze teoriche tra i due concetti, ma solo come differiscono all'interno di Mockito stesso.

Quando Mockito crea un mock, lo fa dalla classe di un tipo, non da un'istanza reale. Il mock crea semplicemente un'istanza di shell ridotta all'osso della Classe, interamente strumentata per tracciare le interazioni con essa.

D'altra parte, la spia avvolgerà un'istanza esistente . Si comporterà comunque nello stesso modo dell'istanza normale: l'unica differenza è che sarà anche strumentato per tenere traccia di tutte le interazioni con esso.

Nell'esempio seguente, creiamo un mock della classe ArrayList :

@Test public void whenCreateMock_thenCreated() { List mockedList = Mockito.mock(ArrayList.class); mockedList.add("one"); Mockito.verify(mockedList).add("one"); assertEquals(0, mockedList.size()); }

Come possiamo vedere, l'aggiunta di un elemento all'elenco deriso in realtà non aggiunge nulla: chiama semplicemente il metodo senza altri effetti collaterali.

Una spia d'altra parte si comporterà in modo diverso - sarà effettivamente chiamare la vera attuazione del add metodo e aggiungere l'elemento alla lista sottostante:

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

6. Comprensione del Mockito NotAMockException

In questa sezione finale, impareremo a conoscere Mockito NotAMockException . Questa eccezione è una delle eccezioni comuni che probabilmente incontreremo quando utilizziamo in modo improprio derisioni o spie .

Cominciamo vedendo in quali circostanze può verificarsi questa eccezione:

List list = new ArrayList(); Mockito.doReturn(100).when(list).size(); assertEquals("Size should be 100: ", 100, list.size()); 

Quando eseguiamo questo snippet di codice, otteniamo il seguente errore:

org.mockito.exceptions.misusing.NotAMockException: Argument passed to when() is not a mock! Example of correct stubbing: doThrow(new RuntimeException()).when(mock).someMethod(); 

Per fortuna è abbastanza chiaro dal messaggio di errore di Mockito qual è il problema qui. Nel nostro esempio, l' oggetto list non è un mock. Il metodo Mockito when () si aspetta un oggetto fittizio o spia come argomento .

Come possiamo anche vedere, il messaggio di eccezione descrive anche come dovrebbe apparire una chiamata corretta. Ora che abbiamo una migliore comprensione di quale sia il problema, risolviamolo seguendo la raccomandazione:

final List spyList = Mockito.spy(new ArrayList()); Mockito.doReturn(100).when(spyList).size(); assertEquals("Size should be 100: ", 100, spyList.size()); 

Il nostro esempio ora si comporta come previsto e non vediamo più l'eccezione Mockito NotAMockException.

7. Conclusione

In questo rapido articolo, abbiamo discusso gli esempi più utili di utilizzo delle spie Mockito.

Abbiamo imparato come creare una spia , come utilizzare l' annotazione @Spy , come stub una spia e, infine, la differenza tra Mock e Spy .

L'implementazione di tutti questi esempi può essere trovata su GitHub .

Questo è un progetto Maven, quindi dovrebbe essere facile da importare ed eseguire così com'è.

E, naturalmente, per più bontà di Mockito, dai un'occhiata alla serie qui.