Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unit testing a DAO class that uses Spring JDBC

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 the RowMapper 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!

like image 350
Alex Ciminian Avatar asked Mar 23 '11 10:03

Alex Ciminian


People also ask

How do you test for DAO?

Enzyme test: Dao is an analytical test which is carried out in the laboratory using the ELISA method to measure the level of the DAO enzyme in the blood and thus to identify whether the migraine is caused by a deficit in DAO. You should fast for a minimum of eight hours prior to the extraction of blood.

Does spring support unit testing?

Spring includes a number of classes that can help with unit testing. They fall into two categories: General Testing Utilities. Spring MVC Testing Utilities.

What is spring JDBC used for?

It provides methods to query and update data in a database and is oriented toward relational databases. JDBC offers a natural Java interface for working with SQL. JDBC is needed to provide a “pure Java” solution for application development. JDBC API uses JDBC drivers to connect with the database.


2 Answers

Please have a look at below links:

  1. Testing SQL queries with Spring and DbUnit
  2. MockObjects or DBUnit for testing Code using JdbcTemplate

Hope that helps.

EDIT:

Here is the GitHub version of RowMapperTests for easy reference.

like image 158
Nilesh Avatar answered Oct 23 '22 16:10

Nilesh


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.

like image 37
skaffman Avatar answered Oct 23 '22 17:10

skaffman