I'm writing a test for a method that throws various exception. This test case is to throw SQLException and I noticed these behavior.
@Test
public void testGetPreparedStatement_throwsSQLException() throws Exception {
try (MockedStatic<DriverManager> mockedDriverManager = mockStatic(DriverManager.class)) {
// Throws org.mockito.exceptions.misusing.UnfinishedStubbingException
mockedDriverManager.when(() -> DriverManager.getConnection(anyString(), anyString(), anyString()))
.thenThrow(new SQLException("some message"));
assertThrows(SQLException.class, () -> ((RequestDBServiceJDBC) RequestDBServiceJDBC.getInstance())
.getPreparedStatement(new RequestCriteria()));
}
}
// But somehow this works:
SQLException sqlException = new SQLException("some message");
mockedDriverManager.when(() -> DriverManager.getConnection(anyString(), anyString(), anyString()))
.thenThrow(sqlException);
Error:
org.mockito.exceptions.misusing.UnfinishedStubbingException:
Unfinished stubbing detected here:
-> at at com.devcenter.myproject.request.service.jdbc.RequestDBServiceJDBCTest.testGetPreparedStatement_throwsSQLException(RequestDBServiceJDBCTest.java:206)
E.g. thenReturn() may be missing.
Examples of correct stubbing:
when(mock.isOk()).thenReturn(true);
when(mock.isOk()).thenThrow(exception);
doThrow(exception).when(mock).someVoidMethod();
Hints:
1. missing thenReturn()
2. you are trying to stub a final method, which is not supported
3. you are stubbing the behaviour of another mock inside before 'thenReturn' instruction is completed
at java.sql/java.sql.DriverManager.getLogWriter(DriverManager.java:129)
at java.sql/java.sql.SQLException.<init>(SQLException.java:125)
at com.devcenter.myproject.request.service.jdbc.RequestDBServiceJDBCTest.testGetPreparedStatement_throwsSQLException(RequestDBServiceJDBCTest.java:207)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
Is there any explanation for this?
SQLException
constructor calls DriverManager.getLogWriter
.
It is not allowed to call methods of mocked class before you finished when().thenXXX()
sequence.
You have to construct exception before when
called.
Alternatively you can use .then(x -> { throw new SQLException("some message");})
instead of thenThrow
.