2012-08-29 3 views
15

Sto provando a simulare un metodo per vedere se gestisco correttamente un'eccezione. Questo è quanto posso ottenere.Eccezione di Mockito in doThrow che sembra corretta

interfaccia:

interface SampleManager { 
    void deleteVariome(String specimenId, String analysisId) throws Exception; 
    // ... 
} 

unit test:

// ... 
SampleManger sampleManager = mock(SampleManager.class); 

// below is line 753 
doThrow(Exception.class).when(sampleManager).deleteVariome(sample1.getId(), analysisId); 

risultato:

org.mockito.exceptions.misusing.UnfinishedStubbingException: 
Unfinished stubbing detected here: 
-> at ...server.ArchiveManagerImplUTest.deleteVariomeFails(ArchiveManagerImplUTest.java:753) 

E.g. thenReturn() may be missing. 
Examples of correct stubbing: 
    when(mock.isOk()).thenReturn(true); 
    when(mock.isOk()).thenThrow(exception); 
    doThrow(exception).when(mock).someVoidMethod(); <-- this looks a log like what I did! 

Hints: 

1. missing thenReturn() 

2. you are trying to stub a final method, you naughty developer! <-- I have a lot of other mocks of this interface in this test that work. 

risposta

0

è necessario fornire una esempio del Exception.class non la classe Exception sé .

doThrow(new Exception()).when(sampleManager).deleteVariome(sample1.getId(), analysisId); 

EDIT Beh @DavidWallace mi corresse, quindi state attenti (o meglio illuminato) che dal 1,9 si può solo fornire la classe di eccezione per lanciare e sarà costruire uno per voi.

+2

No, da Mockito 1.9.0 in poi, è possibile fornire la classe di eccezione, e che funzionerà come previsto.Tuttavia, anche se l'OP utilizza una vecchia versione di Mockito, non otterrebbero il sintomo che stanno descrivendo qui. Credo che il problema sia qualcosa di diverso. –

+0

Grazie David. Non lo sapevo. Lascerò qui la mia risposta in modo che altri possano essere consapevoli del tuo commento. –

4

Questo errore viene in genere segnalato DOPO il luogo in cui si è verificato effettivamente. Se non riesci a stub correttamente, Mockito di solito non può dire fino al momento in cui NEXT chiami uno dei metodi Mockito. Questo potrebbe essere lo stesso metodo di prova, un metodo di test successivo nella stessa classe o anche una classe di test completamente diversa.

La linea che hai citato mi sembra a posto. Dai un'occhiata alle righe sopra di esso, dove chiami un metodo di stub o verifica di Mockito. È molto probabile che tu disponga di un when non associato a thenReturn, then o thenThrow. Oppure potresti avere un verify che manca la chiamata al metodo reale. Ci sono anche altre possibilità.

Se non riesci a trovare un errore nelle linee SOPRA quello che hai citato, quindi pubblica un altro po 'del tuo codice, e darò un'occhiata più da vicino.

+1

Inoltre, se si utilizza il runner JUnit 'MockitoJUnitRunner.class', Mockito verificherà che il metodo di test non abbia alcuna stub non completata. Questo aiuterà a isolare questo errore all'origine del problema. – Brice

+0

in OP: Se vuoi assicurarti che sia il problema, è facile: basta eseguire quel particolare metodo di test e dovresti trovare che funzioni bene. Oppure puoi mettere un reset di prova appena prima della tua effettiva logica di test, e potresti trovare che il test funzioni bene. Questi sono i sintomi del problema descritto da David Wallace –

+0

Ma il problema potrebbe essere in realtà lo stesso metodo di prova. Quindi potresti ricevere l'errore eseguendo solo l'unico metodo di prova. In tal caso, anche l'uso di 'MockitoJUnitRunner' non ti aiuterà. –

17

Da un problema identico a cui mi sono imbattuto, ho il sospetto che sample sia un mock e che tu abbia soppresso sample.getId() altrove? Ciò ha causato comunque questo problema nel mio caso.

Per qualche motivo, Mockito si arrabbia se uno degli argomenti che si passa allo stub utilizzato con doThrow in questo modo è il risultato di un metodo che si è anche deriso. Forse è una specie di controllo di re-entrancy per evitare loop infiniti, non lo so.

Indipendentemente da ciò, provare a sostituire sample.getId() con un valore costante e che dovrebbe risolvere il problema. Potresti considerare di usare una costante dichiarata nel tuo test sia per il finto che per ogni ulteriore utilizzo di esso. Potresti anche verificare che il metodo che stai testando utilizza sample.getId() aggiungendo un'altra chiamata a verify.

+0

Ho affrontato lo stesso problema ... risolto senza passare un valore costante anziché un finto. –

+0

grazie amico! Lo risolvo passando nel metodo 'thenReturn' una variabile locale invece del valore direttamente dal getter. – Juancho

4

Come descritto nella risposta di Gijs, questo è probabilmente dovuto a un bug in Mockito. Ecco un test completo che riproduce:

interface Sample { String getId(); } 
interface SampleManager { 
    void deleteVariome(String specimenId, String analysisId); 
} 

@Test 
public void probableMockitoBug() { 
    Sample sample1 = mock(Sample.class); 
    when(sample1.getId()).thenReturn("a"); 

    SampleManager manager = mock(SampleManager.class); 
    doThrow(Exception.class).when(manager).deleteVariome(sample1.getId(), "b"); 

    manager.deleteVariome("a", "b"); 
} 

Il test produce il seguente output:

 
org.mockito.exceptions.misusing.UnfinishedStubbingException: 
Unfinished stubbing detected here: 
-> at org.mockitousage.JavadocExamplesTest.probableMockitoBug(JavadocExamplesTest.java:404) 

E.g. thenReturn() may be missing. 
Examples of correct stubbing: 
    when(mock.isOk()).thenReturn(true); 
    when(mock.isOk()).thenThrow(exception); 
    doThrow(exception).when(mock).someVoidMethod(); 
Hints: 
1. missing thenReturn() 
2. you are trying to stub a final method, you naughty developer! 

    at org.mockito.exceptions.Reporter.unfinishedStubbing(Reporter.java:55) 
    at org.mockito.internal.progress.MockingProgressImpl.validateState(MockingProgressImpl.java:74) 
    at org.mockito.internal.progress.ThreadSafeMockingProgress.validateState(ThreadSafeMockingProgress.java:49) 
    at org.mockito.internal.MockHandler.handle(MockHandler.java:71) 
    at org.mockito.internal.InvocationNotifierHandler.handle(InvocationNotifierHandler.java:36) 
    at org.mockito.internal.creation.MethodInterceptorFilter.intercept(MethodInterceptorFilter.java:48) 
    at org.mockitousage.JavadocExamplesTest$Sample$$EnhancerByMockitoWithCGLIB$$d5ac41.getId() 
    at org.mockitousage.JavadocExamplesTest.probableMockitoBug(JavadocExamplesTest.java:404) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at org.mockito.internal.runners.JUnit45AndHigherRunnerImpl.run(JUnit45AndHigherRunnerImpl.java:37) 
    at org.mockito.runners.MockitoJUnitRunner.run(MockitoJUnitRunner.java:62) 
+0

In tal caso, la soluzione semplice è: 'doThrow (Exception.class) .when (manager) .deleteVariome (" a "," b ");' –