I'm using mockito in a junit test. How do you make an exception happen and then assert that it has (generic pseudo-code)
16 Answers
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 Comments
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
Dependencies
4 Comments
caughtException ?com.googlecode.catchexception.CatchException.caughtException;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
1 Comment
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")); } 3 Comments
given() where does this come from?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).
3 Comments
verify call assert the exception?when clause is correct, it must have thrown an exception.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); } Comments
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
Comments
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); } Comments
Here is a way, how you can Mock and Assert the exception:
- Java 8 or above
- JUnit 5 ->
org.junit.jupiter:5.X.X&org.mockito:4.X.X
// Mock an exception when(mapperService.convertRequest(any())).thenThrow(new RuntimeException()); // Assert the exception RuntimeException thrown = Assertions.assertThrows(RuntimeException.class, () -> { addOfferService.processData(deltaDetails); }); Assertions.assertEquals("Exception occurred during create data", thrown.getMessage()); Comments
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.
Mockito fully supports stubbing methods to throw an exception, AssertJ is not necessary.
Code below. First the stuff that will be tested:
@Component public class Blam { public void blamIt() { System.out.println("blam"); } } @Component @RequiredArgsConstructor public class Kapow { private final Blam blam; public void aMethod() { blam.blamIt(); } } Now the actual unit test (using Mockito and Junit 5):
@ExtendWith(MockitoExtension.class) public class TestKapow { private Kapow classToTest; @Mock private Blam mockBlam; @Mock private RuntimeException mockRuntimeException; @BeforeEach void beforeEach() { classToTest = new Kapow(mockBlam); } @Test void aMethod_blamItThrowsRuntimeException_exceptionEscapes() { final RuntimeException actualException; doThrow(mockRuntimeException).when(mockBlam).blamIt(); actualException = assertThrows(RuntimeException.class, () -> classToTest.aMethod()); assertNotNull(actualException); assertSame(mockRuntimeException, actualException); } } Some Notes:
- I find it to be a good practice to instantiate mock objects via the
@Mockannotation. - I prefer the
doThrow(xxx).when(mockXxx).methodform for throwing and exception during a unit test. - You can "catch" the thrown exception when using the
assertThrowsmethod.
Comments
If you are handling an exception and execute code in this block, you cat tests it as follows:
@Service @RequiredArgConstructor class ServiceClass { private final Repository repository; private final SecondService secondService; public String getObjFromDB(String code){ try{ String obj = repository.findObj(code); }catch(Exception e){ secondService.doSomeThing(e); throw new RuntimeException(e); } } } // ====
@SpringBootTest class SomeTest { @Autowired ServiceClass serviceClass; @MockBean SecondService secondService; @MockBean Repository repository; @Test public void getObjFromDBTest(){ Exception exception = new RuntimeException(); doThrow(exception) .when(repository).findObj(any(String.class)); doNothing() .when(secondService).doSomeThing(exception); assertThrows(RuntimeException.class, () -> servceClass.getObjFromDB(code)); verify(secondService, times(1)).doSomeThing(exception) } } Comments
Assert by exception message:
try { MyAgent.getNameByNode("d"); } catch (Exception e) { Assert.assertEquals("Failed to fetch data.", e.getMessage()); }