4

我正在用 JUnit 编写一些集成测试。这里发生的情况是,当我连续(而不是单独)运行所有测试时,数据库中持久保存的数据总是会发生变化,并且测试在执行过程中会发现意外数据(由先前的测试插入)。

我正在考虑使用 DbUnit,但我想知道它是否会在每次执行之间重置自动增量索引(因为测试还会检查持久实体的 ID)。

谢谢

M。

4

4 回答 4

9

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

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

于 2010-05-03T17:03:40.577 回答
3

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

或者,让您的测试数据库由脚本创建。DbUnit 可以在这里提供帮助,其他数据库生成器也可以,例如LiquiBasedbmaintaindbmigrate您可以删除整个数据库并为每个测试或测试组重新创建。随着测试数据集变大和开销增加,这种方法的用处会降低。

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

EDIT: The OP asked about using hibernate to recreate the schema. This can be arranged by creating a new SessionFactory for each test and setting the "hibernate.hbm2ddl.auto" to "true" when building the SessionFactory. I mention the diminishing effectiveness of drop-create - it appies to this case too.

于 2010-05-03T17:12:38.697 回答
2

It is bad to rely on id values in a test, cause auto-increment are database specific only. So i would never check the id's, cause if you do so your test depends that the entities are filled with particular id values which is not a real life example. A test should be independent of auto-increment id's.

于 2010-05-03T17:13:01.357 回答
1

本质上,这个问题可以通过两种方式解决。

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

  2. 使用类似 DBUnit 等的东西来模拟与 DB 操作相关的类,这样就不会有数据进入 DB,并且您的类会返回结果,就好像 DB 操作已经完成一样。

如果您在运行测试时访问数据库,我更喜欢方法 1。

于 2010-05-03T16:44:29.433 回答