2012-05-29 11 views
68

Durante la scrittura di un nuovo test Junit4, mi chiedo se utilizzare @RunWith (MockitoJUnitRunner.class) o MockitoAnnotations.initMocks (questo).@RunWith (MockitoJUnitRunner.class) vs MockitoAnnotations.initMocks (questo)

Ho creato un nuovo test & la procedura guidata ha generato automaticamente un test con il Runner. Javadocs per lo stato MockitoJUnitRunner la seguente:

Compatibile con JUnit 4.4 e superiori, questo corridore aggiunge seguente comportamento:

Inizializza deride annotato con Mock, in modo che l'utilizzo esplicito di MockitoAnnotations.initMocks (oggetto) non è necessario . I mazzi sono inizializzati prima di ogni metodo di prova. convalida l'utilizzo della struttura dopo ogni metodo di prova.

Non è chiaro se con il corridore ha qualche vantaggio rispetto alle initMocks() metodo che ho usato in passato.

Qualsiasi pensiero o collegamento sarebbe apprezzato!

risposta

85

MockitoJUnitRunner fornisce la convalida automatica dell'utilizzo del framework, nonché un initMocks() automatico.

Vale la pena la validazione automatica dell'utilizzo del framework. Ti dà un resoconto migliore se fai uno di questi errori.

  • si chiama il metodo statico when, ma non concludono i stubbing con un corrispondente thenReturn, thenThrow o then. (errore 1 nel seguente codice)

  • Si chiama verify su un finto, ma dimentica di fornire la chiamata al metodo che si sta tentando di verificare. (Errore 2 nel seguente codice)

  • si chiama il metodo when dopo doReturn, doThrow o doAnswer e passare un finto, ma dimentica di fornire il metodo che si sta cercando di stub. (errore 3 nel seguente codice)

Se non si dispone di convalida di utilizzo quadro, questi errori non sono segnalati fino a quando il seguente chiamata a un metodo Mockito.Questo potrebbe essere

  • nello stesso metodo di prova (come errore 1 sotto),
  • nel metodo di prova successiva (come errore 2 sotto),
  • nella prossima classe di test.

Se si verificano nell'ultimo test eseguito (come l'errore 3 di seguito), non verranno segnalati affatto.

Ecco come potrebbero apparire ciascuno di questi tipi di errori. Supponiamo qui che JUnit esegua questi test nell'ordine in cui sono elencati qui.

@Test 
public void test1() { 

    // ERROR 1 
    // This compiles and runs, but it's an invalid use of the framework because 
    // Mockito is still waiting to find out what it should do when myMethod is called. 
    // But Mockito can't report it yet, because the call to thenReturn might 
    // be yet to happen. 
    when(myMock.method1()); 

    doSomeTestingStuff(); 

    // ERROR 1 is reported on the following line, even though it's not the line with 
    // the error. 
    verify(myMock).method2(); 

} 

@Test 
public void test2() { 

    doSomeTestingStuff(); 

    // ERROR 2 
    // This compiles and runs, but it's an invalid use of the framework because 
    // Mockito doesn't know what method call to verify. But Mockito can't report 
    // it yet, because the call to the method that's being verified might 
    // be yet to happen. 
    verify(myMock); 
} 

@Test 
public void test3() { 

    // ERROR 2 is reported on the following line, even though it's not even in 
    // the same test as the error. 
    doReturn("Hello").when(myMock).method1(); 


    // ERROR 3 
    // This compiles and runs, but it's an invalid use of the framework because 
    // Mockito doesn't know what method call is being stubbed. But Mockito can't 
    // report it yet, because the call to the method that's being stubbed might 
    // be yet to happen. 

    doReturn("World").when(myMock); 

    doSomeTestingStuff(); 

    // ERROR 3 is never reported, because there are no more Mockito calls. 
} 

Ora, quando ho scritto questa risposta più di cinque anni fa, ho scritto

Quindi mi sento di raccomandare l'uso del MockitoJUnitRunner, ove possibile. Tuttavia, come ha giustamente sottolineato Tomasz Nurkiewicz, non è possibile utilizzarlo se hai bisogno di un altro corridore JUnit, come quello di Primavera.

La mia raccomandazione è ora cambiata. Il team di Mockito ha aggiunto una nuova funzione da quando ho scritto questa risposta per la prima volta. È una regola JUnit, che svolge esattamente la stessa funzione dello MockitoJUnitRunner. Ma è meglio, perché non preclude l'uso di altri corridori.

Includere

@Rule 
public MockitoRule rule = MockitoJUnit.rule(); 

nella classe di test. Questo inizializza i mock e automatizza la convalida del framework; proprio come fa MockitoJUnitRunner. Ma ora puoi usare SpringJUnit4ClassRunner o qualsiasi altro JUnitRunner. Da Mockito 2.1.0 in poi, ci sono opzioni aggiuntive che controllano esattamente quale tipo di problemi vengono segnalati.

+3

Vedi le [javadocs per 'Mockito.validateMockitoUsage()'] (http://docs.mockito.googlecode.com/hg/latest/org/mockito/Mockito.html#validateMockitoUsage%28%29) per ulteriori informazioni convalida. – avandeursen

+0

Non posso assolutamente dire che siano uguali. in un caso di test, il programma di installazione JUnit corridore non riesce per me e non iniettare miei schernisce correttamente a meno che non faccio il setup initMocks – dtc

+0

Stiamo usando TestNG 6.8.8 + Mockito 1.10.19 e, ovviamente, non possiamo usare MockitoJUnitRunner, ma il framework di validazione funziona ancora! E funziona esattamente come @ David Wallace. Qualcuno può spiegare? Questo perché abbiamo ancora @ Prima * callback e MockitoAnnotations.initMocks (questo)? – yuranos87

23

L'utilizzo del runner consente di salvare un po 'di codice (non è necessario il metodo @Before). D'altra parte, l'uso di un corridore a volte non è possibile, cioè quando ne stai già utilizzando uno, come SpringJUnit4ClassRunner.

Questo è tutto. È solo una questione di preferenza.

+1

Oltre alla riga initMocks(), il metodo @Before sarebbe ancora necessario per qualsiasi altra configurazione, giusto? – OceanBlue

+1

@OceanBlue: Ovviamente se il metodo '@ Before' contiene qualcosa tranne' initMocks() 'di quanto tu debba preservarlo dopo la migrazione al runner. –

+0

La risposta di David Wallace sulla validazione della struttura risponde pienamente alla mia domanda, quindi ho accettato quella, ma +1 per sottolineare che questo corridore non può essere usato con un altro, come quello di Primavera. Grazie! – OceanBlue

Problemi correlati