对使用 Spring JDBC 的 DAO 类进行单元测试
Posted
技术标签:
【中文标题】对使用 Spring JDBC 的 DAO 类进行单元测试【英文标题】:Unit testing a DAO class that uses Spring JDBC 【发布时间】:2011-07-21 04:43:10 【问题描述】:我有几个 DAO 对象用于从数据库中检索信息,我真的想为它们编写一些自动化测试,但我很难弄清楚如何去做。
我正在使用 Spring 的 JdbcTemplate
运行实际查询(通过准备好的语句)并将结果映射到模型对象(通过 RowMapper
类)。
如果我要编写单元测试,我不确定我会/应该如何模拟对象。例如,由于只有读取,我会使用实际的数据库连接,而不是模拟 jdbcTemplate,但我不确定这是否正确。
这是批处理中最简单的 DAO 的(简化)代码:
/**
* 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());
任何想法都将不胜感激。
谢谢!
【问题讨论】:
你可以看看Acolyte,一个对JDBC持久性进行单元测试的框架,真正的隔离 【参考方案1】:请查看以下链接:
-
Testing SQL queries with Spring and DbUnit
MockObjects or DBUnit for testing Code using JdbcTemplate
希望对您有所帮助。
编辑:
这里是GitHub version of RowMapperTests,方便参考。
【讨论】:
SpringSource 已移至 github,您可以找到 RowMapperTests here。编辑:我已经用新链接更新了答案。【参考方案2】:我建议您打破对JdbcTemplate
类的依赖,并改用JdbcOperations
接口,例如
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
您的单元测试可以调用第二个构造函数,传入一个模拟 JdbcOperations
对象。由于所有 DB 操作都是通过 jdbc
对象执行的,因此您可以轻松地模拟它。
您的实时代码可以像以前一样调用第一个构造函数。
【讨论】:
【参考方案3】:要为此编写真正的单元测试,您不会接触到真正的数据库。 但是,您可能会发现将真实的 DataSource 传递到底层数据库并测试 getBusinessSegments() 方法返回 0、1 和许多结果,具体取决于您传入的 cc 和 ll 值。
另一个值得研究的选项是传入一个嵌入式Java DB 的数据源,该数据源是在 setUp/@Before 方法中使用您的架构初始化的。我猜您真正想要测试的是 SELECT... 查询是否正确映射到架构,因此这样的测试将捕获运行时出现的任何错误,例如架构更改。
【讨论】:
以上是关于对使用 Spring JDBC 的 DAO 类进行单元测试的主要内容,如果未能解决你的问题,请参考以下文章