Throwing checked exceptions with Mockito can be challenging if the method signature does not declare the exception. However, there are several workarounds to achieve this:
1. Using `willAnswer()` or `doAnswer()`**
One effective way to throw checked exceptions is by using the `willAnswer()` method from BDDMockito or the `doAnswer()` method in plain Mockito. These methods allow you to specify a custom behavior for the mock object, including throwing checked exceptions.
Here's an example using `doAnswer()`:
java
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
// Define a checked exception
public class SomeException extends Exception {
public SomeException(String message) {
super(message);
}
}
// In your test class
@Test(expectedExceptions = SomeException.class)
public void throwCheckedException() {
List list = Mockito.mock(List.class);
// Use doAnswer to throw a checked exception
Mockito.doAnswer(new Answer() {
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
throw new SomeException("Custom checked exception");
}
}).when(list).get(0);
list.get(0); // This will throw the checked exception
}
2. Throw Unchecked Exceptions**
If the method signature does not allow checked exceptions, you can throw unchecked exceptions instead. This is often recommended because Mockito works smoothly with unchecked exceptions.
For example, if you're mocking a `List` interface, you can throw an `ArrayIndexOutOfBoundsException`, which is an unchecked exception:
java
@Test(expectedExceptions = ArrayIndexOutOfBoundsException.class)
public void throwUncheckedException() {
List list = Mockito.mock(List.class);
when(list.get(0)).thenThrow(new ArrayIndexOutOfBoundsException());
list.get(0); // This will throw the unchecked exception
}
3. Modify the Method Signature**
If you have control over the method you're testing, you can modify its signature to declare the checked exception. This way, Mockito will not throw an error when you use `thenThrow()` to simulate the exception.
For instance, if you have an interface like this:
java
interface SomeInterface {
void someMethod() throws SomeException;
}
You can then mock it to throw the checked exception without issues:
java
SomeInterface mock = Mockito.mock(SomeInterface.class);
when(mock.someMethod()).thenThrow(new SomeException());
4. Use Kotlin's `given` Function**
If you're using Kotlin, you can leverage its `given` function from the `mockk` library or use Mockito's `thenAnswer` in a Kotlin context to throw checked exceptions.
Here's how you might do it with Mockito in Kotlin:
kotlin
@Test(expectedExceptions = SomeException::class)
fun throwCheckedException() {
val list: List = mock()
whenever(list.get(0)).thenAnswer { throw SomeException("Custom message") }
list.get(0) // This will throw the checked exception
}
These workarounds allow you to effectively test scenarios involving checked exceptions with Mockito, even when the method signature does not explicitly declare them.
Citations:[1] https://www.janbasktraining.com/community/java/throw-checked-exceptions-from-mocks-with-mockito
[2] https://www.w3docs.com/snippets/java/mockito-how-to-mock-and-assert-a-thrown-exception.html
[3] https://reflectoring.io/clean-unit-tests-with-mockito/
[4] https://stackoverflow.com/questions/3762047/throw-checked-exceptions-from-mocks-with-mockito
[5] https://www.youtube.com/watch?v=CCVhVSYPaMo
[6] https://rollbar.com/blog/how-to-handle-checked-unchecked-exceptions-in-java/
[7] https://blog.sammkinng.in/blogs/checked-exception-is-invalid-for-this-method
[8] https://www.tutorialspoint.com/mockito/mockito_exception_handling.htm
[9] https://www.browserstack.com/guide/mockito-throw-exception