I need to mock a JDBC update statement, and I want to make sure that the update string sent is the correct one. I have a MockConnectionManager that has the following method defined for defining the expected query strings:
public void setUpdateExpectedQuery(String ...expectedQueryStrings) throws SQLException {
Statement mockStatement = mock(Statement.class);
when(mockConnection.createStatement()).thenReturn(mockStatement);
when(mockStatement.executeUpdate(anyString())).then(new Answer<String>() {
@Override
public String answer(InvocationOnMock invocationOnMock) throws Throwable {
String str = Arrays.toString(invocationOnMock.getArguments());
throw new RuntimeException("Update string is not as expected: " + str);
}
});
for(String expected : expectedQueryStrings) {
when(mockStatement.executeUpdate(expected)).then(new Answer<Void>() {
@Override
public Void answer(InvocationOnMock invocationOnMock) throws Throwable {
// Do something, just don't throw an exception here.
return null;
}
});
}
}
I want that if an unexpected query string was encountered an exception will be thrown. The query strings we expect are below as mentioned in the Mockito wiki (http://docs.mockito.googlecode.com/hg/latest/org/mockito/Mockito.html#2).
For some reason, when executing the test and just calling the setUpdateExpectedQuery, an exception is thrown.
MockConnectionManager connectionManager = (MockConnectionManager) context.getBean("connectionManager");
connectionManager.setUpdateExpectedQuery("INSERT WHATEVER INTO WHENEVER");
The same exception as written in the first Answer: java.lang.RuntimeException: Update string is not as expected: [INSERT WHATEVER INTO WHENEVER]
How is this possible? is calling 'when' actually invokes the method? I never saw it happening in other cases...
I suspect the problem is that your calls within the loop (when you call mockStatement.executeUpdate(expected)
) match your earlier mock of when(mockStatement.executeUpdate(anyString()))
.
Remember that the way the mock knows what you're calling within the when
is because you're calling it - imagine translating when(mockStatement.executeUpdate(anyString()))
into:
int result = mockStatement.executeUpdate(anyString());
OngoingStubbing<Integer> tmp = when(result);
tmp.then(...);
It may be that you just need to have a single when(...)
call. So:
public void setUpdateExpectedQuery(String ...expectedQueryStrings)
throws SQLException {
final Set<String> capturedQueries = new HashSet<>
(Arrays.asList(expectedQueryStrings);
Statement mockStatement = mock(Statement.class);
when(mockConnection.createStatement()).thenReturn(mockStatement);
when(mockStatement.executeUpdate(anyString())).then(new Answer<String>() {
@Override
public String answer(InvocationOnMock invocationOnMock) throws Throwable {
String query = (String) invocationOnMock.getArguments[0];
if (capturedQueries.contains(query)) {
return null;
}
throw new RuntimeException("Update string is not as expected: " + query);
}
});
}
See more on this question at Stackoverflow