Unit testing a DAO class that uses Spring JDBC
Solution 1
Please have a look at below links:
- Testing SQL queries with Spring and DbUnit
- MockObjects or DBUnit for testing Code using JdbcTemplate
Hope that helps.
EDIT:
Here is the GitHub version of RowMapperTests for easy reference.
Solution 2
I recommend breaking your dependency on JdbcTemplate
class, and using the JdbcOperations
interface instead, e.g.
public class GPLBusinessSegmentDAO implements BusinessSegmentDAO {
private final JdbcOperations jdbc;
public GPLBusinessSegmentDAO(DataSource dataSource) {
this(new JdbcTemplate(dataSource));
}
public GPLBusinessSegmentDAO(JdbcOperations jdbc) {
this.jdbc = jdbc;
}
// ... DAO methods here
}
Your unit test can invoke the second constructor, passing in a mock JdbcOperations
object. Since all DB operations are performed via the jdbc
object, you can mock that easily enough.
Your live code can call the first constructor as before.
Solution 3
To write a true unit test for this, you would not be touching a real database. You may however find it more practical to pass in a real DataSource to your underlying db, and test the getBusinessSegments() method returns 0, 1 and many results depending on the cc and ll values you pass in.
Another option worth investigating would be to pass in a DataSource of an embedded Java DB that was initialised with your schema in a setUp/@Before method. I guess what you really want to test is that the SELECT... query maps correctly to the schema, so such a test would catch any errors that arise at runtime when the schema, say, changes.
Related videos on Youtube
Alex Ciminian
Updated on December 24, 2020Comments
-
Alex Ciminian over 3 years
I have several DAO objects that are used to retrieve information from a database and I really want to write some automated tests for them but I'm having a hard time figuring out how to do it.
I'm using Spring's
JdbcTemplate
to run the actual query (via a prepared statement) and map the results to the model object (via theRowMapper
class).If I were to write unit tests, I'm not sure how I would/should mock the objects. For example, since there are only reads, I would use the actual database connection and not mock the jdbcTemplate, but I'm not sure that's right.
Here's the (simplified) code for the simplest DAO of the batch:
/** * Implementation of the {@link BusinessSegmentDAO} interface using JDBC. */ public class GPLBusinessSegmentDAO implements BusinessSegmentDAO { private JdbcTemplate jdbcTemplate; private static class BusinessSegmentRowMapper implements RowMapper<BusinessSegment> { public BusinessSegment mapRow(ResultSet rs, int arg1) throws SQLException { try { return new BusinessSegment(rs.getString(...)); } catch (SQLException e) { return null; } } } private static class GetBusinessSegmentsPreparedStatementCreator implements PreparedStatementCreator { private String region, cc, ll; private int regionId; private GetBusinessSegmentsPreparedStatementCreator(String cc, String ll) { this.cc = cc; this.ll = ll; } public PreparedStatement createPreparedStatement(Connection connection) throws SQLException { String sql = "SELECT ..."; PreparedStatement ps = connection.prepareStatement(sql); ps.setString(1, cc); ps.setString(2, ll); return ps; } } public GPLBusinessSegmentDAO(DataSource dataSource) { jdbcTemplate = new JdbcTemplate(dataSource); } public Collection<BusinessSegment> getBusinessSegments(String cc, String ll) { return jdbcTemplate.query( new GetBusinessSegmentsPreparedStatementCreator(cc, ll), new BusinessSegmentRowMapper()); } }
Any idea would be appreciated.
Thanks!
-
Tony R over 12 yearsNow that SpringSource has moved to github, you can find RowMapperTests here. EDIT: I have updated the answer with the new link.