如何在java中对DAO应用单元测试

时间:2013-08-20 03:35:41

标签: java unit-testing dao

我不知道如何在数据访问层上应用单元测试。我总是想知道是否应该测试数据访问层。在我的公司,我们有稳定的数据库来存储单元测试数据和测试数据访问层,方法是运行数据访问对象并检查它们从稳定数据库中获取的数据。

为了通过单元测试,不能再修改稳定数据库中的数据。我认为有更好的解决方案。如果我没有弄错,模拟对象就无法对SQL语句和ResultSet映射执行测试。

对DAO进行单元测试的最佳方法是什么?使用TDD有更好的方法吗?

4 个答案:

答案 0 :(得分:10)

首先,根据大多数定义,“单元”测试不依赖于像数据库这样的外部系统。您想要创建所谓的“功能”或“集成”测试。在实践中,这些类型的测试将以与单元测试相同的方式实现,使用类似Junit的东西,但是您应该将它们与单元测试分开,单元测试应该非常快速运行,并且在数据库关闭或数据发生变化时不会中断。

其次,尝试将大部分业务逻辑保留在DAO之外,而不是将其放入服务POJO层,以便您可以在不涉及数据库的情况下测试业务逻辑。

接下来,设置DAO测试的理想方法是从空数据库开始,并使用测试数据加载它(通常使用DAO本身),然后针对已知且可写的测试运行DAO测试数据集。如果您有幸拥有只读数据库,那么您概述的stable database方法将起作用,但大多数系统都可以读/写数据库。

最后,测试DAO很有价值。数据库查询通常是系统中最脆弱的部分,您不希望等到它们部署到生产环境中才能发现它们正在崩溃。

答案 1 :(得分:2)

严格来说,您正在编写功能测试。要做到这一点,您将需要一种或另一种测试数据库。让我们谈谈你的选择。

  1. HSQL /内存数据库。小而快。在单元测试大小的数据上进行设置和滚动,以及出色的性能是微不足道的。缺点是,除非您使用这些环境进行部署,否则您可能会面临单元测试工作但实际代码失败的风险。这也意味着您无法使用HSQL和生产数据库都不支持的任何SQL结构。通过使用Hibernate或类似功能可以在一定程度上减轻这种情况。如果您只有非常简单的查询,那么这是一个很好的方法。

  2. 完全模拟数据库调用。除非你在你的DAO中做太多繁重的工作,否则毫无意义。

  3. 使用生产数据库的测试实例。这将在准确性或结果方面为您提供最佳结果。它将允许您进行测试以确保所有调用都按预期工作,并允许您使用非可移植SQL。您可以使用类似DBUnit的内容来加载数据库数据,或者只使用待测试的DAO来执行此操作。如果您有大而讨厌的查询,我会推荐这个。有很多边缘案例,汇总视图和微妙行为。缺点是真正的数据库会因为他们正在进行实际工作(事务,索引更新,回滚支持)而导致性能损失。

答案 2 :(得分:1)

一些意见/建议:

  1. DAO测试的目的是验证查询是否已触发,检索的数据是否符合预期。在DAO中几乎没有任何业务逻辑可供测试。
  2. 由于主要目标是测试数据库交互,因此模拟不会使其变得万无一失,特别是边缘情况。
  3. 鉴于此,您现在采用的方法是公平的。我不确定为什么你觉得它不好。一点点阐述会有所帮助。
  4. 如果您不方便使用外部数据库,那么您可以使用Java的内置javaDB。请注意,在运行此测试之前,首先要创建测试数据。

答案 3 :(得分:0)

对于基于JDBC的项目,可以模拟JDBC连接,以便可以在没有实时RDBMS的情况下执行测试,每个测试用例都是隔离的(没有数据冲突)。

允许验证,持久性代码传递正确的查询/参数(例如https://github.com/playframework/playframework/blob/master/framework/src/anorm/src/test/scala/anorm/ParameterSpec.scala)并按预期处理JDBC结果(解析/映射)。

jOOQ或我的框架之类的框架Acolyte可以用于:https://github.com/cchantep/acolyte