Reputation: 1939
I'm writing an unit test for spring jdbc dao. The method to test is:
public long getALong() {
return simpleJdbcTemplate.queryForObject("sql query here", new RowMapper<Long>() {
public Long mapRow(ResultSet resultSet, int i) throws SQLException {
return resultSet.getLong("a_long");
}
});
}
Here is what I have in the test:
public void testGetALong() throws Exception {
final Long result = 1000L;
context.checking(new Expectations() {{
oneOf(simpleJdbcTemplate).queryForObject("sql_query", new RowMapper<Long>() {
public Long mapRow(ResultSet resultSet, int i) throws SQLException {
return resultSet.getLong("a_long");
}
});
will(returnValue(result));
}});
Long seq = dao.getALong();
context.assertIsSatisfied();
assertEquals(seq, result);
}
Naturally, the test doesn't work (otherwise, I wouldn't be asking this question here). The problem is the rowmapper in the test is different from the rowmapper in the DAO. So the expectation is not met.
I tried to put with
around the sql query and with(any(RowMapper.class))
for the rowmapper. It wouldn't work either, complains about "not all parameters were given explicit matchers: either all parameters must be specified by matchers or all must be specified by values, you cannot mix matchers and values"
Upvotes: 1
Views: 6801
Reputation: 2707
I think you might be missing a couple of points here. Your first attempt reproduced the behaviour of the target code in the mock. What are you really trying to test?
For this kind of test, I prefer to write a focussed test that hits a real database. I tried mocking out the JDBC many years ago and regretted it. What usually fails in this kind of code is the relationship with the database, rather than the java code itself.
This is really a query (it doesn't change the state of the world outside the object), so I tend to use an allowing()
clause rather than oneOf()
. It's the same underlying mechanism but expresses the intent better.
Finally, rather than calling context.assertIsSatisfied()
directly, consider using
@RunWith(JMock.class)
at the top of the test.
Upvotes: 2
Reputation: 1939
I solved the problem by adding with(any(Object.class))
at the end.
oneOf(jdbcTemplate).queryForObject(with(equal("sql_query")), with(any(RowMapper.class)), with(any(Object.class)));
I think jmock was having trouble finding the right method to call, since queryForObject method get overloaded so much.
Upvotes: 1
Reputation: 45576
Provide a matcher for query string as well, e.g.
oneOf(simpleJdbcTemplate).queryForObject(
with( equal("sql_query") ),
with( any(RowMapper.class) )
);
Upvotes: 2