2012-11-05 19 views
49

Sto testando un metodo con un'eccezione prevista. Devo anche verificare che sia stato chiamato un codice di pulizia (su un oggetto fittato) dopo che l'eccezione è stata lanciata, ma sembra che la verifica sia stata ignorata. Ecco il codice. Sto usando Junit ExpectedExceptionRule per verificare l'eccezione prevista.Mockito verifica dopo l'eccezione Junit 4.10

@Rule 
public ExpectedException expectedEx = ExpectedException.none(); 

@Test 
public void testExpectedException() 
{ 
    MockedObject mockObj = mock(MockedObj.class); 
    MySubject subject = new MySubject(mockedObj); 
    expectedEx.expect(MyException.class); 
    expectedEx.expectMessage("My exception message."); 
    subject.someMethodThrowingException(); 
    verify(mockObj). 
     someCleanup(eq(...)); 
} 

Sembra che lo verify venga completamente ignorato. Non importa quale metodo inserisco nel verify, il mio test sta passando, che non è quello che voglio.

Qualche idea del perché questo è felice?

risposta

51

ExpectedException funziona con wrapping your entire test method in un blocco try-catch tramite JUnit @Rule. Quando il tuo codice genera un'eccezione, sale allo stack sul try/catch più vicino, che si trova nell'istanza ExpectedException (che controlla che sia l'eccezione che ti aspetti).

In Java, se si verifica un'eccezione non rilevata in un metodo, il controllo non restituirà mai più istruzioni in quel metodo. Le stesse regole si applicano qui: Il controllo non ritorna mai alle istruzioni nel test dopo l'eccezione.

Tecnicamente, è possibile inserire le verifiche in un blocco finale, ma che tende ad essere a bad habit. In ogni caso, è probabile che ingerisca l'utile messaggio ExpectedException, poiché verrebbe eseguito prima che la regola ExpectedException possa intercettarlo.

Se avete veramente bisogno di verificare lo stato dopo l'eccezione, in base al metodo, si può sempre tornare a questo idioma:

@Test 
public void testExpectedException() 
{ 
    MockedObject mockObj = mock(MockedObj.class); 
    MySubject subject = new MySubject(mockedObj); 
    try { 
    subject.someMethodThrowingException(); 
    fail("Expected MyException."); 
    } catch (MyException expected) { 
    assertEquals("My exception message.", expected.getMessage()); 
    } 
    verify(mockObj).someCleanup(eq(...)); 
} 

Aggiornamento: con Java 8 di espressioni lambda, è possibile avvolgere una chiamata all'interfaccia funzionale in un blocco try concisely enough to be useful. Immagino che il supporto per questa sintassi troverà la sua strada in molte librerie di test standard.

assertThrows(MyException.class, 
    () -> systemUnderTest.throwingMethod()); 
4

non ho ancora provato questo, ma oltre a risposta eccellente di Jeff Bowman, si potrebbe avere la scelta di utilizzare la Regola ExpectedException con una prova ... finalmente costruire, ponendo la sua dichiarazione di verificare nel fine bloccare.

+0

Controllare il mio punto di mezzo ... penso che avrebbe funzionato, ma sarebbe ingoiare il messaggio ExpectedException. Grazie per il complimento però! –

+0

Mancato quello - probabilmente giusto. –

+3

Finalmente funziona bene per me - esegue la verifica e rileva ancora l'eccezione prevista e il suo messaggio –

6

soluzione più elegante con catch-exception

@Test 
public void testExpectedException() 
{ 
    MockedObject mockObj = mock(MockedObject.class); 
    MySubject subject = new MySubject(mockObj); 

    when(subject).someMethodThrowingException(); 

    then(caughtException()) 
      .isInstanceOf(MyException.class) 
      .hasMessage("My exception message."); 

    verify(mockObj).someCleanup(eq(...)); 
} 
Problemi correlati