Mockito — Stubbing methods with exceptions
When can use Mockito’s when-thenThrow or doThrow-when methods to stub exceptions.
Examples
Example application
package com.logicbig.example; public interface MyService
package com.logicbig.example; public class MyProcessor < private MyService myService; public MyProcessor(MyService myService) < this.myService = myService; >public String process() < int returnInteger = myService.doSomething(); return String.format("My Integer is: " + returnInteger); >public String process2() throws Exception < int returnInteger = myService.doSomething2(); return String.format("My Integer is: " + returnInteger); >public String process3() < try < int returnInteger = myService.doSomething2(); return String.format("My Integer is: " + returnInteger); >catch (Exception e) < System.out.println("-- exception thrown in MyProcess --"); return "default-value"; >> >
Testing exceptions
Testing unchecked exception
package com.logicbig.example; import junit.framework.TestCase; import org.junit.Assert; import org.junit.Test; import org.mockito.Mockito; public class ProcessorTest < @Test public void processTest() < MyService myService = Mockito.mock(MyService.class); Mockito.when(myService.doSomething()).thenThrow(new RuntimeException("Cannot process")); MyProcessor myProcessor = new MyProcessor(myService); try < String returnedValue = myProcessor.process(); TestCase.fail(); >catch (Exception e) < System.out.println("-- exception thrown --"); Assert.assertTrue(e instanceof RuntimeException); Assert.assertEquals(e.getMessage(), "Cannot process"); >> >
D:\mockito-throwing-exception-in-subbing>mvn test -Dtest="ProcessorTest"
[INFO] Scanning for projects.
[INFO]
[INFO] -----< com.logicbig.example:mockito-throwing-exception-in-subbing >-----
[INFO] Building mockito-throwing-exception-in-subbing 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ mockito-throwing-exception-in-subbing ---
[WARNING] Using platform encoding (Cp1252 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO]
[INFO] --- maven-compiler-plugin:3.8.1:compile (default-compile) @ mockito-throwing-exception-in-subbing ---
[INFO] Changes detected - recompiling the module!
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ mockito-throwing-exception-in-subbing ---
[WARNING] Using platform encoding (Cp1252 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO]
[INFO] --- maven-compiler-plugin:3.8.1:testCompile (default-testCompile) @ mockito-throwing-exception-in-subbing ---
[INFO] Changes detected - recompiling the module!
[INFO]
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ mockito-throwing-exception-in-subbing ---
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running com.logicbig.example.ProcessorTest
-- exception thrown --
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.888 sec
Results :
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 5.793 s
[INFO] Finished at: 2020-05-13T00:29:01-05:00
[INFO] ------------------------------------------------------------------------
Note that if we try to throw checked exception in above example i.e.
Mockito.when(myService.doSomething()).thenThrow(new Exception("Cannot process"));
then we will have following runtime exception:
org.mockito.exceptions.base.MockitoException:
Checked exception is invalid for this method!
Invalid: java.lang.Exception: Cannot process
at com.logicbig.example.ProcessorTest.processTest(ProcessorTest.java:13)
Testing checked exception
package com.logicbig.example; import junit.framework.TestCase; import org.junit.Assert; import org.junit.Test; import org.mockito.Mockito; public class ProcessorTest2 < @Test public void processTest() throws Exception < MyService myService = Mockito.mock(MyService.class); Mockito.when(myService.doSomething2()).thenThrow(new Exception("Cannot process")); MyProcessor myProcessor = new MyProcessor(myService); try < String returnedValue = myProcessor.process2(); TestCase.fail(); >catch (Throwable e) < System.out.println("-- exception thrown --"); Assert.assertTrue(e instanceof Exception); Assert.assertEquals(e.getMessage(), "Cannot process"); >> >
D:\mockito-throwing-exception-in-subbing>mvn test -Dtest="ProcessorTest2"
[INFO] Scanning for projects.
[INFO]
[INFO] -----< com.logicbig.example:mockito-throwing-exception-in-subbing >-----
[INFO] Building mockito-throwing-exception-in-subbing 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ mockito-throwing-exception-in-subbing ---
[WARNING] Using platform encoding (Cp1252 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO]
[INFO] --- maven-compiler-plugin:3.8.1:compile (default-compile) @ mockito-throwing-exception-in-subbing ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ mockito-throwing-exception-in-subbing ---
[WARNING] Using platform encoding (Cp1252 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO]
[INFO] --- maven-compiler-plugin:3.8.1:testCompile (default-testCompile) @ mockito-throwing-exception-in-subbing ---
[INFO] Changes detected - recompiling the module!
[INFO]
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ mockito-throwing-exception-in-subbing ---
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running com.logicbig.example.ProcessorTest2
-- exception thrown --
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 1.312 sec
Results :
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 5.591 s
[INFO] Finished at: 2020-05-13T00:35:38-05:00
[INFO] ------------------------------------------------------------------------
Testing handled exception
public class ProcessorTest3 < @Test public void processTest() throws Exception < MyService myService = Mockito.mock(MyService.class); Mockito.when(myService.doSomething2()).thenThrow(new Exception("Cannot process")); MyProcessor myProcessor = new MyProcessor(myService); String returnedValue = myProcessor.process3(); Assert.assertEquals(returnedValue, "default-value"); >>
D:\mockito-throwing-exception-in-subbing>mvn test -Dtest="ProcessorTest3"
[INFO] Scanning for projects.
[INFO]
[INFO] -----< com.logicbig.example:mockito-throwing-exception-in-subbing >-----
[INFO] Building mockito-throwing-exception-in-subbing 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ mockito-throwing-exception-in-subbing ---
[WARNING] Using platform encoding (Cp1252 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO]
[INFO] --- maven-compiler-plugin:3.8.1:compile (default-compile) @ mockito-throwing-exception-in-subbing ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ mockito-throwing-exception-in-subbing ---
[WARNING] Using platform encoding (Cp1252 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO]
[INFO] --- maven-compiler-plugin:3.8.1:testCompile (default-testCompile) @ mockito-throwing-exception-in-subbing ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ mockito-throwing-exception-in-subbing ---
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running com.logicbig.example.ProcessorTest3
-- exception thrown in MyProcess --
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.757 sec
Results :
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 3.830 s
[INFO] Finished at: 2020-05-13T00:36:36-05:00
[INFO] ------------------------------------------------------------------------
Using doThrow-when method
package com.logicbig.example; import junit.framework.TestCase; import org.junit.Assert; import org.junit.Test; import org.mockito.Mockito; public class ProcessorTest4 < @Test public void processTest() < MyService myService = Mockito.mock(MyService.class); Mockito.doThrow(new RuntimeException("Cannot process")).when(myService).doSomething(); MyProcessor myProcessor = new MyProcessor(myService); try < String returnedValue = myProcessor.process(); TestCase.fail(); >catch (Exception e) < System.out.println("-- exception thrown --"); Assert.assertTrue(e instanceof RuntimeException); Assert.assertEquals(e.getMessage(), "Cannot process"); >> >
D:\mockito-throwing-exception-in-subbing>mvn test -Dtest="ProcessorTest4"
[INFO] Scanning for projects.
[INFO]
[INFO] -----< com.logicbig.example:mockito-throwing-exception-in-subbing >-----
[INFO] Building mockito-throwing-exception-in-subbing 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ mockito-throwing-exception-in-subbing ---
[WARNING] Using platform encoding (Cp1252 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO]
[INFO] --- maven-compiler-plugin:3.8.1:compile (default-compile) @ mockito-throwing-exception-in-subbing ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ mockito-throwing-exception-in-subbing ---
[WARNING] Using platform encoding (Cp1252 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO]
[INFO] --- maven-compiler-plugin:3.8.1:testCompile (default-testCompile) @ mockito-throwing-exception-in-subbing ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ mockito-throwing-exception-in-subbing ---
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running com.logicbig.example.ProcessorTest4
-- exception thrown --
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.861 sec
Results :
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 3.656 s
[INFO] Finished at: 2020-05-13T00:37:35-05:00
[INFO] ------------------------------------------------------------------------
We should use doThrow() when we want to stub the void method with an exception.
Example Project
Dependencies and Technologies Used:
- mockito-core 3.3.3: Mockito mock objects library core API and implementation.
- junit 4.13: JUnit is a unit testing framework for Java, created by Erich Gamma and Kent Beck.
- JDK 8
- Maven 3.5.4
throw checked Exceptions from mocks with Mockito
For example the following works (and doesn’t throw a MockitoException but actually throws a checked Exception as required here) using BDDMockito :
given(someObj.someMethod(stringArg1)).willAnswer( invocation -> < throw new Exception("abc msg"); >);
The equivalent for plain Mockito would to use the doAnswer method
Check the Java API for List.
The get(int index) method is declared to throw only the IndexOutOfBoundException which extends RuntimeException .
You are trying to tell Mockito to throw an exception SomeException() that is not valid to be thrown by that particular method call.
To clarify further.
The List interface does not provide for a checked Exception to be thrown from the get(int index) method and that is why Mockito is failing.
When you create the mocked List, Mockito will use the definition of List.class to creates its mock.
The behavior you are specifying with the when(list.get(0)).thenThrow(new SomeException()) doesn’t match the method signature in List API, because get(int index) method does not throw SomeException() so Mockito fails.
If you really want to do this, then have Mockito throw a new RuntimeException() or even better throw a new ArrayIndexOutOfBoundsException() since the API specifies that that is the only valid Exception to be thrown.