Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

throw checked Exceptions from mocks with Mockito

I'm trying to have one of my mocked objects throw a checked Exception when a particular method is called. I'm trying the following.

@Test(expectedExceptions = SomeException.class)
public void throwCheckedException() {
    List<String> list = mock(List.class);
    when(list.get(0)).thenThrow(new SomeException());
    String test = list.get(0);
}

public class SomeException extends Exception {
}

However, that produces the following error.

org.testng.TestException: 
Expected exception com.testing.MockitoCheckedExceptions$SomeException but got org.mockito.exceptions.base.MockitoException: 
Checked exception is invalid for this method!
Invalid: com.testing.MockitoCheckedExceptions$SomeException

Looking at the Mockito documentation, they only use RuntimeException, is it not possible to throw checked Exceptions from a mock object with Mockito?

like image 406
Arthur Maltson Avatar asked Oct 04 '22 11:10

Arthur Maltson


People also ask

How do you throw a checked exception?

Checked exception (compile time exception)If the compiler does not see a try or catch block or throws keyword to handle a checked exception, it throws a compilation error. Checked exceptions are generally caused by faults outside code like missing files, invalid class names, and networking errors.

What is MockitoException?

MockitoException is RuntimeException raised by Mockito framework to emit an error either due to Mockito, or due to the User.

Can Mockito throw exceptions on void methods?

Mockito provides following methods that can be used to mock void methods. doAnswer() : We can use this to perform some operations when a mocked object method is called that is returning void. doThrow() : We can use doThrow() when we want to stub a void method that throws exception.


2 Answers

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.

like image 343
John Engelman Avatar answered Oct 12 '22 16:10

John Engelman


A workaround is to use a willAnswer() method.

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

like image 194
Deepak Avatar answered Oct 12 '22 17:10

Deepak