Mockito Strict Stubbing e The Unn NeedStubbingException

1. Panoramica

In questo breve tutorial, impareremo a conoscere Mockito UnnecessarioStubbingException . Questa eccezione è una delle eccezioni comuni che probabilmente incontreremo quando si utilizzano gli stub in modo errato.

Inizieremo spiegando la filosofia alla base dello stubbing rigoroso e perché Mockito ne incoraggia l'uso per impostazione predefinita. Successivamente, daremo un'occhiata a cosa significa esattamente questa eccezione e in quali circostanze può verificarsi. Per concludere, vedremo un esempio di come possiamo sopprimere questa eccezione nei nostri test.

Per ulteriori informazioni sui test con Mockito, controlla la nostra serie completa di Mockito.

2. Strict Stubbing

Con la versione 1.x di Mockito era possibile configurare e interagire con i mock senza alcun tipo di restrizione. Ciò significava che, nel tempo, i test sarebbero spesso diventati troppo complicati e talvolta più difficili da eseguire il debug.

Dalla versione 2.+, Mockito ha introdotto nuove funzionalità che spingono il framework verso il "rigore". Gli obiettivi principali alla base di questo sono:

  • Rileva gli stub inutilizzati nel codice di prova
  • Ridurre la duplicazione del codice di test e il codice di test non necessario
  • Promuovi test più puliti rimuovendo il codice "morto"
  • Aiuta a migliorare la capacità di debug e la produttività

Il rispetto di questi principi ci aiuta a creare test più puliti eliminando il codice di test non necessario . Aiutano anche a evitare errori di copia-incolla e altre sviste degli sviluppatori.

Per riassumere, lo stubbing rigoroso segnala gli stub non necessari, rileva la mancata corrispondenza degli argomenti dello stubbing e rende i nostri test più DRY (Don't Repeat Yourself). Ciò facilita una base di codice pulita e gestibile.

2.1. Configurazione di stub rigorosi

A partire da Mockito 2. +, lo stubbing rigoroso viene utilizzato per impostazione predefinita quando si inizializzano i nostri mock utilizzando uno dei seguenti:

  • MockitoJUnitRunner
  • MockitoJUnit.rule ()

Mockito consiglia vivamente l'uso di uno dei due precedenti . Tuttavia, c'è anche un altro modo per abilitare lo stubbing rigoroso nei nostri test quando non stiamo sfruttando la regola o il runner Mockito:

Mockito.mockitoSession() .initMocks(this) .strictness(Strictness.STRICT_STUBS) .startMocking(); 

Un ultimo punto importante da sottolineare è che in Mockito 3.0, tutti gli stubbing saranno "rigorosi" e convalidati per impostazione predefinita.

3. Esempio di Unn neededStubbingException

In poche parole, uno stub non necessario è una chiamata al metodo bloccata che non è mai stata realizzata durante l'esecuzione del test.

Diamo un'occhiata a un semplice esempio:

@Test public void givenUnusedStub_whenInvokingGetThenThrowUnnecessaryStubbingException() { when(mockList.add("one")).thenReturn(true); // this won't get called when(mockList.get(anyInt())).thenReturn("hello"); assertEquals("List should contain hello", "hello", mockList.get(1)); }

Quando eseguiamo questo test unitario, Mockito rileverà lo stub inutilizzato e genererà un'eccezione Non necessariaStubbing :

org.mockito.exceptions.misusing.UnnecessaryStubbingException: Unnecessary stubbings detected. Clean & maintainable test code requires zero unnecessary code. Following stubbings are unnecessary (click to navigate to relevant line of code): 1. -> at com.baeldung.mockito.misusing.MockitoUnecessaryStubUnitTest.givenUnusedStub_whenInvokingGetThenThrowUnnecessaryStubbingException(MockitoUnecessaryStubUnitTest.java:37) Please remove unnecessary stubbings or use 'lenient' strictness. More info: javadoc for UnnecessaryStubbingException class.

Per fortuna, è abbastanza chiaro dal messaggio di errore qual è il problema qui. Possiamo anche vedere che il messaggio di eccezione ci indica persino la riga esatta che causa l'errore.

Perché succede questo? Bene, il primo quando l' invocazione configura il nostro mock per restituire true quando chiamiamo il metodo add con l'argomento "uno" . Tuttavia, non invochiamo questo metodo durante il resto dell'esecuzione dello unit test.

Mockito ci sta dicendo che la nostra prima linea quando è ridondante e forse abbiamo commesso un errore durante la configurazione dei nostri stub.

Sebbene questo esempio sia banale, è facile immaginare, quando si prende in giro una complessa gerarchia di oggetti, come questo tipo di messaggio possa aiutare il debugging ed essere altrimenti molto utile.

4. Bypassare lo stubbing rigoroso

Infine, vediamo come bypassare gli stub rigorosi. Questo è anche noto come stubbing indulgente.

A volte è necessario configurare uno stubbing specifico per essere indulgente mantenendo tutti gli altri stubbing e mock per utilizzare lo stubbing rigoroso:

@Test public void givenLenientdStub_whenInvokingGetThenThrowUnnecessaryStubbingException() { lenient().when(mockList.add("one")).thenReturn(true); when(mockList.get(anyInt())).thenReturn("hello"); assertEquals("List should contain hello", "hello", mockList.get(1)); }

Nell'esempio sopra, utilizziamo il metodo statico Mockito.lenient () per abilitare lo stubbing indulgente sul metodo di aggiunta della nostra lista di mock.

Gli stub indulgenti aggirano le regole di convalida di "stubbing rigoroso". Ad esempio, quando lo stubbing è dichiarato indulgente, non verrà controllato per potenziali problemi di stubbing come lo stubbing non necessario descritto in precedenza.

5. conclusione

In questo breve articolo, abbiamo iniziato introducendo il concetto di stubbing rigoroso in Mockito e abbiamo capito la filosofia alla base del perché è stato introdotto e perché è importante.

Successivamente, abbiamo esaminato un esempio di Unn NeedStubbingException prima di terminare con un esempio di come abilitare lo stubbing indulgente nei nostri test.

Come sempre, il codice sorgente completo dell'articolo è disponibile su GitHub.