192

I'm using mockito in a junit test. How do you make an exception happen and then assert that it has (generic pseudo-code)

0

16 Answers 16

255

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()); 
Sign up to request clarification or add additional context in comments.

3 Comments

this approach is unacceptable for case when you're testing method of an object that has some state. For example there is an object method that throws exception if you call it the second time. And you need to test to test that it does throw exception during the second method call, not the first one. If it throws MyException during the first method call (in the preparation stage) then it should fail the test. But with this approach we are not able to check during which method call the exception is thrown.
Though in this case we can catch exception from the first method call and wrap it in RuntimeException.
this does not work if the method doSomething() return type is void?
89

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

What is "catch-exception"? Got a link?
what's caughtException ?
Got it, it's coming from com.googlecode.catchexception.CatchException.caughtException;
will catch-exception still print the stacktrace?
49

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

worked for me...Also we can check the exception message as well.assertThatThrownBy(() -> myService.sumTingWong("badArg")).hasMessage("test") .isInstanceOf(IllegalArgumentException.class);
39

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?
I also prefer to use the @Rule, because this way I can test for expected message or cause or other stuff pertaining to the exception. For checking the cause of the exception, I use: expectedException.expectCause(Mockito.sameInstance(expectedException)) or expectedException.expectCause(Mockito.instanceOf(MyException.class)) and a few others that come in handy.
22

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(); 

Comments

20

I think this should do it for you.

assertThrows(someException.class, ()-> mockedServiceReference.someMethod(param1,parme2,..)); 

Comments

18

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

Does the verify call assert the exception?
@NilsH No. But provided the when clause is correct, it must have thrown an exception.
if the method someMethod() return type is void, then it does not work like this. is there any way we can mock throw exception for void methods?
18

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

11

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

8

An easy and short way that worked for me was:

assertThrows(YourException.class, () -> yourLogic()) 

Comments

4

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

1

Here is a way, how you can Mock and Assert the exception:

  1. Java 8 or above
  2. 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

0

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.

2 Comments

@MariuszS response correctly answers what you are saying is unrelated to Mockito
@pringi Thanks, I see that the question concerned both mocking an exception and catching it. I wonder though if this depends on any behaviour of the code under test.
0

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:

  1. I find it to be a good practice to instantiate mock objects via the @Mock annotation.
  2. I prefer the doThrow(xxx).when(mockXxx).method form for throwing and exception during a unit test.
  3. You can "catch" the thrown exception when using the assertThrows method.

Comments

0

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

-3

Assert by exception message:

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

1 Comment

If written like this, when there is no exception thrown, the test will still pass. Which is what we want to avoid in the first place

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.