Mockito ¿Cómo burlarse y afirmar una excepción lanzada?


Respuestas:


75

Solución de estilo BDD (actualizada a Java 8)

Mockito por sí solo no es la mejor solución para manejar excepciones, use Mockito con Catch-Exception

Mockito + Catch-Exception + AssertJ

given(otherServiceMock.bar()).willThrow(new MyException());

when(() -> myService.foo());

then(caughtException()).isInstanceOf(MyException.class);

Código de muestra

Dependencias


2
¿Qué es "excepción de captura"? ¿Tienes un enlace?
Duncan Jones el

lo que es caughtException?
Saif Masadeh

Lo tengo, viene decom.googlecode.catchexception.CatchException.caughtException;
Saif Masadeh

212

Para responder a su segunda pregunta primero. Si está usando JUnit 4, puede anotar su prueba con

@Test(expected=MyException.class)

para afirmar que ha ocurrido una excepción. Y para "burlarse" de una excepción con mockito, use

when(myMock.doSomething()).thenThrow(new MyException());

2
este enfoque es inaceptable para el caso cuando está probando el método de un objeto que tiene algún estado. Por ejemplo, hay un método de objeto que arroja una excepción si lo llama por segunda vez. Y debe probar para comprobar que arroja una excepción durante la segunda llamada al método, no la primera. Si arroja MyException durante la primera llamada al método (en la etapa de preparación), entonces debe fallar la prueba. Pero con este enfoque no podemos verificar durante qué método se produce la llamada a la excepción.
Sneg

Aunque, en este caso, podemos detectar la excepción de la primera llamada al método y envolverla en RuntimeException.
Sneg

29

Si también desea probar el mensaje de excepción, puede usar ExpectedException de JUnit con Mockito:

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

@Test
public void testExceptionMessage() throws Exception {
    expectedException.expect(AnyException.class);
    expectedException.expectMessage("The expected message");

    given(foo.bar()).willThrow(new AnyException("The expected message"));
}

given()¿De donde viene esto?
Mohammad Faisal


También prefiero usar la @Rule, porque de esta manera puedo probar el mensaje esperado o la causa u otras cosas relacionadas con la excepción. Para verificar la causa de la excepción, uso: expectException.expectCause (Mockito.sameInstance (pectedException)) opectedException.expectCause (Mockito.instanceOf (MyException.class)) y algunos otros que son útiles.
Crenguta S

19

Respuesta actualizada para 19/06/2015 (si está utilizando Java 8)

Solo usa afirmar

Usando afirj-core-3.0.0 + Java 8 Lambdas

@Test
public void shouldThrowIllegalArgumentExceptionWhenPassingBadArg() {
assertThatThrownBy(() -> myService.sumTingWong("badArg"))
                                  .isInstanceOf(IllegalArgumentException.class);
}

Referencia: http://blog.codeleak.pl/2015/04/junit-testing-exceptions-with-java-8.html


funcionó para mí ... También podemos verificar el mensaje de excepción también.
Sritam Jagadev

17

Si usa JUnit 4 y Mockito 1.10.x Anote su método de prueba con:

@Test(expected = AnyException.class)

y para lanzar su excepción deseada use:

Mockito.doThrow(new AnyException()).when(obj).callAnyMethod();

16

Haz que la excepción suceda así:

when(obj.someMethod()).thenThrow(new AnException());

Verifique que haya sucedido ya sea afirmando que su prueba arrojará tal excepción:

@Test(expected = AnException.class)

O por verificación simulada normal:

verify(obj).someMethod();

La última opción es necesaria si su prueba está diseñada para probar que el código intermedio maneja la excepción (es decir, la excepción no se lanzará desde su método de prueba).


¿La verifyllamada afirma la excepción?
NilsH

@NilsH No. Pero siempre que la whencláusula sea correcta, debe haber arrojado una excepción.
Duncan Jones el

10

Use doThrow de Mockito y luego capture la excepción deseada para afirmar que se lanzó más tarde.

@Test
public void fooShouldThrowMyException() {
    // given
    val myClass = new MyClass();
    val arg = mock(MyArgument.class);
    doThrow(MyException.class).when(arg).argMethod(any());
    Exception exception = null;

    // when
    try {
        myClass.foo(arg);
    } catch (MyException t) {
        exception = t;
    }

    // then
    assertNotNull(exception);
}

5

Usando mockito, puedes hacer que la excepción suceda.

when(testingClassObj.testSomeMethod).thenThrow(new CustomException());

Usando Junit5, puede afirmar una excepción, afirma si esa excepción se produce cuando se invoca el método de prueba .

@Test
@DisplayName("Test assert exception")
void testCustomException(TestInfo testInfo) {
    final ExpectCustomException expectEx = new ExpectCustomException();

     InvalidParameterCountException exception = assertThrows(InvalidParameterCountException.class, () -> {
            expectEx.constructErrorMessage("sample ","error");
        });
    assertEquals("Invalid parametercount: expected=3, passed=2", exception.getMessage());
}

Encuentre una muestra aquí: afirmar excepción junit


Gracias ! Trabajó para mí
HariKishore

1

Sin relación con mockito, uno puede atrapar la excepción y afirmar sus propiedades. Para verificar que la excepción sucedió, afirme una condición falsa dentro del bloque try después de la declaración que arroja la excepción.


La respuesta de @MariuszS responde correctamente lo que usted dice que no está relacionado con Mockito
pringi

@pringi Gracias, veo que la pregunta se refería tanto a burlarse de una excepción como a captarla. Sin embargo, me pregunto si esto depende de cualquier comportamiento del código bajo prueba.
anguila ghEEz

1

O si su excepción se produce desde el constructor de una clase:

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

@Test
public void myTest() {    

    exception.expect(MyException.class);
    CustomClass myClass= mock(CustomClass.class);
    doThrow(new MyException("constructor failed")).when(myClass);  

}

-1

Afirmar por mensaje de excepción:

    try {
        MyAgent.getNameByNode("d");
    } catch (Exception e) {
        Assert.assertEquals("Failed to fetch data.", e.getMessage());
    }

Si se escribe así, cuando no se produce una excepción, la prueba aún pasará . Que es lo que queremos evitar en primer lugar
Christian Lim
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.