2010-05-03 85 views
4

我在JUnit中编写了一些集成测试。这里发生的事情是,当我在一行(而不是单独)中一起运行所有测试时,数据库中保存的数据总是会更改,测试在执行期间会发现意外数据(由以前的测试插入)。我想使用DbUnit,但我不知道它是否重置每次执行之间的自动递增索引(因为测试还检查持久化实体的ID)。集成测试 - 休眠和DbUnit

感谢

M.

回答

9

这是一个最好的做法是把你的数据库中已知的状态前的测试执行和DBUnit的提供所需的一切。但不要依赖于自动递增的列,也可以将它们放在DBUnit数据集中。优点:您可以在执行失败的测试后手动验证数据库状态。缺点:您需要设置和维护数据集。

另一种方法是在事务内部运行每个测试方法(并在执行结束时回滚事务)。优点:数据更容易设置和维护(在数据库中)。缺点:修复失败的测试不太方便。

1

本质上那朵问题可以从两个方面来解决。

  1. 在交易中包装与数据库相关的测试。在测试之前开始交易。测试运行结束后,中止交易将中止交易。这样,测试中所做的任何更改都不会被保留。

  2. 使用类似DBUnit等的东西来模拟DB操作相关的类,以便数据不会传到DB,并且您的类像DB操作一样返回结果。

如果您运行测试时访问DB我更喜欢接近1

3

您可以将单个测试或适用的测试组作为单个事务运行,然后在最后回滚。 (如果测试本身包含多个事务并且您的db不支持嵌套事务或保存点,则这可能很困难。)

或者,让您的测试数据库由脚本创建。与其他数据库生成器一样,DbUnit也可以提供帮助,例如LiquiBase,dbmaintain,dbmigrate然后,您可以删除整个数据库并为每个测试或测试组重新创建。随着测试数据集变大并且开销增加,这种方法的有用性会降低。

最后一个选项是不让你的测试依赖于生成的id,因为根据生成的值会产生脆弱的测试。测试生成的id很有用,因此为某些测试测试这些值,但我不确定在测试所有测试的Id时是否有价值。

编辑:OP询问有关使用休眠来重新创建架构。这可以通过为每个测试创建一个新的SessionFactory并在构建SessionFactory时将“hibernate.hbm2ddl.auto”设置为“true”来安排。我提到drop-create的效用越来越小 - 它也适用于这种情况。

+0

如何强制Hibernate手动重置模式?也许在我的基础测试类的@After方法。 – Mark 2010-05-03 19:19:39

+0

当然,如果你的模式目前已经被hibernate管理,那么这是一种可能性。我在回答中增加了一些额外的内容。 – mdma 2010-05-03 20:32:04

+0

请注意尽管可能的话,为每个测试重新创建模式并不会扩展,而且确实很慢。这不是一个好主意IMO。 – 2010-05-04 08:05:10

2

在测试中依靠id值是不好的,因为自动增量只是数据库特定的。所以我永远不会检查ID的,因为如果你这样做,你的测试取决于实体充满特殊的ID值,这不是一个真实的例子。测试应该独立于自动增量ID。