测试方法——DB、Junit

Posted

技术标签:

【中文标题】测试方法——DB、Junit【英文标题】:Testing approach - DB, Junit 【发布时间】:2010-02-09 13:50:47 【问题描述】:

我想问你关于编写与数据库数据相关的测试。在我看来,最好的方法是使用具有正确数据的不同数据库模式,仅用于单元测试。在测试代​​码中,我可以根据 ID 加载对象。

第二种可能性是在单元测试期间将数据放入数据库。不喜欢。

你怎么看。你是怎么做到的?

亲切的问候 塞巴斯蒂安

【问题讨论】:

【参考方案1】:

如果您真的想编写与数据库交互的测试(集成测试),那么您必须在每次测试执行之前将数据库置于已知状态。

一种方法是在每次测试之前加载自定义数据集,例如使用DbUnit。在这里,每个测试负责自己的数据,不需要清理,您可以在测试失败后查询数据库以了解问题。

另一种方法是使用“实时”数据库并在事务内运行测试并在测试结束时回滚更改。 Spring 和 Unitils 对此提供了支持。这也很有效,但是在使用这种方法时诊断失败的测试并不总是那么容易。

请注意,第二种方法并没有真正排除第一种方法,您可以在事务中使用自定义数据集。另请注意,您可以使用包含“参考数据”(即只读数据,如国家等)的数据库,并且在使用第一种方法时仅加载“动态数据”以加快速度。

就我个人而言,我真的看不出前一种方法有什么问题(除了测试可能有点慢),DbUnit 之类的工具使它变得非常容易。正如我所说,我发现使用 DbUnit 的测试更容易诊断。但是后一种方法肯定也有效。

在这两种情况下,您当然应该使用专用架构1

1 实际上,每个开发人员使用一个模式肯定是best practice。

【讨论】:

帕斯卡,很好的详细答案。您在那里提到了它,但我认为强调与实时数据库交互的测试通常是集成测试很重要。使用实时数据库进行单元测试将是矫枉过正,模拟它是合适的。【参考方案2】:

对于单元测试,您应该模拟或存根数据库的功能。由于您正在测试调用数据库的对象而不是数据库本身,因此无需使用真正的数据库。 EasyMock 或 JMock 是很好的模拟库。

【讨论】:

谢谢。如果我有一个大对象图怎么办?然后我需要编写很多代码来模拟对其他对象的每个引用。我在服务层中使用模拟来模拟 DAO 层,因为 DAO 层已经过测试。而且我还使用 GUI 层中的模拟来模拟服务层,因为服务层已经过测试。你不觉得模拟数据库来测试 DAO 层不是一个好主意吗?我们想测试它,但在这种情况下,我们将测试模拟对象。你怎么看?感谢您的回答。 如果要模拟的对象太多,可能意味着你的设计太复杂,一个类可能承担太多责任。没有看到实际代码,很难说,但看看你是否可以简化一下。至于数据库,如果您正在模拟数据库,那么如果您的测试是针对 DAO 的,那么您就不是在测试模拟对象。您正在测试 DAO 是否将正确的命令发送到数据库。对于 DAO 测试,假设数据库将按预期运行是安全的(并且您总是可以模拟它来做意想不到的事情来测试错误案例)。【参考方案3】:

三个cmets:

    单元测试通常是小规模、快速的测试,覆盖一小段代码。使用数据库的测试并不是真正的单元测试(即使你可以在例如 JUnit 中运行它们),而是系统/集成测试。两者都很有用,用于不同的目的。

    即使您的对象图很大,我也不明白为什么您需要在单元测试中一次测试所有对象。您使用必要的模拟对象测试一个 DAO,并断言对象图的相关部分得到正确处理。然后为下一个 DAO 等编写更多测试。

    IMO DAO 通常不应该做非常复杂的事情(除非将部分业务逻辑放入其中,但这是糟糕的设计 - 应该重构而不是试图用扭曲的单元测试来覆盖它)。

【讨论】:

以上是关于测试方法——DB、Junit的主要内容,如果未能解决你的问题,请参考以下文章

备忘:Junit单元测试

Junit单元测试

junit运行多个测试的方法

单元测试工具——JUnit

我的方法的 JUnit 测试

JUnit test 如何做Java静态方法测试