【问题标题】:What is good practice for java agile integration testing DAO -> database?java敏捷集成测试DAO->数据库的良好做法是什么?
【发布时间】:2010-09-23 03:27:22
【问题描述】:

目前针对 Java 环境中的真实数据库模式对 DAO 进行敏捷集成测试的良好做法是什么?

(我所说的“敏捷”是指解决这个问题的最精简、自动化和简单的解决方案)。

我希望实现测试自动化,证明数据访问层与数据库的真实运行实例无缝集成。针对特定供应商数据库测试我们的自定义 SQL 非常重要。 IE。如果我们编写 T-SQL,我们想针对 SQL Server 进行测试。

是否应该将一个数据库专用于所有正在运行的测试,但没有提交?还是每个测试环境都应该有一个专用的数据库?

人们如何处理设置和拆卸? DBUnit 还在流行吗? Spring 有什么帮助?

【问题讨论】:

  • 我不认为[agile] 标签与问题和答案真正相关并将其删除。如果您认为是,当然可以随意回滚。但在这种情况下,您或许应该解释一下什么是敏捷(和非敏捷)集成测试。
  • 我相信它是相关的,因为我想从以最不突兀的方式解决这个问题的人那里得到答案。具体来说,我想利用简单和反馈的敏捷特性。
  • 敏捷在这样使用时听起来像一个空词......没有“敏捷”测试这样的东西。即使一些敏捷方法侧重于工程实践,敏捷实际上更多的是关于组织模式,它不是代码 IMO 的特征(简单、可测试、可扩展、可维护、高质量等)。只是我的 2 美分。

标签: java testing integration-testing dao


【解决方案1】:

针对特定供应商数据库测试我们的自定义 SQL 非常重要

因此,您应该为每个供应商数据库创建一套测试

@RunWith(Suite.class)
@Suite.SuiteClasses({})
public class SQLServerTestSuite {

    @BeforeClass
    public static void setUpClass() throws Exception {

    }

    @AfterClass
    public static void tearDownClass() throws Exception {
        // clean database
    }

}

是否应该将单个数据库专用于所有正在运行的测试,但没有提交?

建议您执行 SQL 命令但使用回滚命令,因为如果使用提交,您可以更改当前测试的状态以及更改其他测试的状态。否则,您可以处理意外行为。

对于每个开发人员,建议使用database sandbox。这允许每个用户以他们认为合适的任何方式修改数据库并使用测试来运行应用程序而不必担心他们的测试与其他用户的测试之间的任何交互

人们如何处理设置和拆卸?

public class PersonTest {

    @Before
    public void setUp() {
        // set up state to run the test
    }

    @After
    public void teardown() {
       // Transaction rollback
    }

}

Transaction rollback pattern 的好处在于 它使数据库保持与我们开始测试时完全相同的状态无论我们对数据库内容进行了哪些更改

DBUnit 还在流行吗?

DBUnit 用于将数据库表与包含以下内容的 XML 文件进行比较 预期值。您应该记住 DBUnit 处理手动编码的设置。然而,尽管这种方法更彻底开发和维护这类测试非常繁琐。此外,测试不会检测到新添加的字段或属性的缺失映射。

Spring 有什么帮助?

Spring 内置了对事务回滚模式的支持,并支持命名参数 (SqlParameterSource),例如,它允许您将纯 jdbc 查询外部化为每个供应商数据库的多行可读 xml 文件

<?xml version="1.0" encoding="UTF-8"?>
<queries>
    <query name="PERSON_BY_ID">
        <![CDATA[
            select 
                *
            from 
                PERSON
            where
                PERSON.ID = :integerId
        ]]>
    </query>
</queries>

注意查询参数。它遵循 JavaScript 代码样式,您将参数类型声明为前缀。现在您可以创建一个类,在其中定义一组命名查询

public class SQLServerQuery {

    public static final String PERSON_BY_ID = "PERSON_BY_ID";

}

对于动态查询,检测查询逻辑中的错误通常很重要,例如使用 。为了捕捉这些类型的错误,我们需要编写用测试数据填充数据库的测试,执行查询,并验证它是否返回了预期的对象。不幸的是,这类测试的编写和执行都很耗时。

【讨论】:

  • @Synesso 最后,如果可能,请使用内存数据库,例如 H2 - 您只需要一个 jar 文件即可“启动”您的内存数据库。您可以在此处获取 h2 jar 文件:hsql.sourceforge.net/m2-repo/com/h2database/h2/1.2.143/…
  • 谢谢。我正在使用 Spring 的 SimpleJDBCTemplate。如何启用“对事务回滚模式的内置支持”?
  • 找到了。因为我们使用的是 SimpleJDBCTemplate,所以对 Spring 的 txn 回滚实现的引用表示赞赏。 HSQL 不会帮助我们,因为我们需要针对服务器本身测试 T-SQL 和 Oracle SQL 方言。
  • @Synesso 看这里static.springsource.org/spring/docs/3.0.x/… Spring 处理事务回滚模式的方式
【解决方案2】:

我会说你的 DAO 的集成测试只需要关注确保 ORM 的 QL 例如HQL 或 JDBC SQL 是有效的。我认为可以合理地假设查询语言本身已经针对多个驱动程序/数据库进行了彻底的测试。遵循这一点,使用诸如 HSQLDB 之类的“内存中”数据库是合理的。

“Spring Test”旨在进行集成测试,非常适合设置 IoC 上下文、提供事务、设置数据库会话、创建模式然后在测试后删除它、在测试后回滚事务......以至于我对将我的一些数据库测试标记为集成测试持观望态度(我个人认为,只要单元测试不跨越进程边界并且它们的设置是无摩擦的,它们就构成了一个合理的单元测试)。

另一方面,一些好的系统测试应该端到端地测试您的系统并使用所有目标数据库。设置系统测试总是需要付出很多努力,而且因为您正在测试系统本身,所以在框架和工具包方面有很多适用的帮助。

【讨论】:

  • 我也强烈推荐使用 Spring Data,因为它可以简化我们 DAO 的编写。
  • 我们没有使用 ORM,因为针对我们供应商的数据库模式的配置是我们不需要的开销。因此,我们编写了自己的 DAO 和 :.我们需要自动化集成测试来确保我们的数据访问层是正确的。我们正在使用 Spring 的 SimpleJDBCTemplate。
  • 无论您是否使用 ORM,都会发生编写自己的 DAO,因此我不确定特定评论是否具有相关性。我的陈述仍然有效,但我将根据 JDBC 考虑对其进行修改。
【解决方案3】:

我认为一个数据库(每个开发人员)应该没问题,只要您确保删除在测试开始时设置的数据。如果您不依赖任何初始数据集,那么您可以简单地清理表。 DBUnit 在这种情况下是一个很好的解决方案。

有时您依赖于一些初始数据集,并非所有测试都依赖于少数测试,主要用于选择查询。如果您依赖于某些数据集,那将变得很棘手。您仍然可以通过在每个测试开始之前运行种子数据并在最后拆除来使用 Dbunit 进行管理,但它会使测试运行更长时间。

在这种情况下,我发现更好的是创建一个简单的实用程序类来保存在测试开始时创建的任何新数据的 id,并在最后将其删除。

【讨论】:

    【解决方案4】:

    也许我不明白您尝试做的事情的目的或为什么选择这种测试方法,但是您是否考虑过使用模拟对象?您可以使用模拟对象编写 Junits 测试并将其与 Hudson 集成以实现自动化。你可以模拟 DAO、preparedstatements、connections、resultsets 等等。

    DAO 是一种经过验证的模式。 JDBC 或您可能用于接口的任何其他东西也是如此。你想证明它有效吗?还是您真的要在 DAO 的方法中测试查询或 SQL?

    【讨论】:

    • 如果我模拟或存根数据库,那么它不再是数据库集成测试。 DAO 是一种模式,但模式并未在测试中 - 实现是。
    • 我的观点完全正确 - “DAO 是一种经过验证的模式。JDBC 或您可能用于接口的其他任何东西也是如此。您是否试图证明它有效?”
    • Mock vs Live DB - 我知道您需要针对实时数据库进行测试,但我认为针对模拟数据库进行测试也是一件好事。为什么?他们测试不同的东西。针对模拟数据库进行测试测试代码是否发出您期望的请求,并按您期望的方式处理数据。另一方面,对实时数据库进行测试可验证这与数据的真实情况相符。
    猜你喜欢
    • 2012-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-13
    • 1970-01-01
    • 1970-01-01
    • 2021-03-25
    • 2010-09-23
    相关资源
    最近更新 更多