I'm using mockito in a junit test. How do you make an exception happen and then assert that it has (generic pseudo-code)
问题:
回答1:
BDD Style Solution (Updated to Java 8)
Mockito alone is not the best solution for handling exceptions, use Mockito with Catch-Exception
Mockito + Catch-Exception + AssertJ
given(otherServiceMock.bar()).willThrow(new MyException());
when(() -> myService.foo());
then(caughtException()).isInstanceOf(MyException.class);
Sample code
- Mockito + Catch-Exception + Assertj full sample
Dependencies
- eu.codearte.catch-exception:catch-exception:2.0
- org.assertj:assertj-core:3.12.2
回答2:
To answer your second question first. If you're using JUnit 4, you can annotate your test with
@Test(expected=MyException.class)
to assert that an exception has occured. And to "mock" an exception with mockito, use
when(myMock.doSomething()).thenThrow(new MyException());
回答3:
If you want to test the exception message as well you can use JUnit's ExpectedException with 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"));
}
回答4:
Make the exception happen like this:
when(obj.someMethod()).thenThrow(new AnException());
Verify it has happened either by asserting that your test will throw such an exception:
@Test(expected = AnException.class)
Or by normal mock verification:
verify(obj).someMethod();
The latter option is required if your test is designed to prove intermediate code handles the exception (i.e. the exception won't be thrown from your test method).
回答5:
Updated answer for 06/19/2015 (if you're using java 8)
Just use assertj
Using assertj-core-3.0.0 + Java 8 Lambdas
@Test
public void shouldThrowIllegalArgumentExceptionWhenPassingBadArg() {
assertThatThrownBy(() -> myService.sumTingWong("badArg"))
.isInstanceOf(IllegalArgumentException.class);
}
Reference: http://blog.codeleak.pl/2015/04/junit-testing-exceptions-with-java-8.html
回答6:
If you're using JUnit 4, and Mockito 1.10.x Annotate your test method with:
@Test(expected = AnyException.class)
and to throw your desired exception use:
Mockito.doThrow(new AnyException()).when(obj).callAnyMethod();
回答7:
Use Mockito's doThrow and then catch the desired exception to assert it was thrown later.
@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);
}
回答8:
Using mockito, you can make the exception happen.
when(testingClassObj.testSomeMethod).thenThrow(new CustomException());
Using Junit5, you can assert exception, asserts whether that exception is thrown when testing method is invoked.
@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());
}
Find a sample here: assert exception junit
回答9:
Or if your exception is thrown from the constructor of a class:
@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);
}
回答10:
Unrelated to mockito, one can catch the exception and assert its properties. To verify that the exception did happen, assert a false condition within the try block after the statement that throws the exception.
回答11:
Assert by exception message:
try {
MyAgent.getNameByNode("d");
} catch (Exception e) {
Assert.assertEquals("Failed to fetch data.", e.getMessage());
}