【发布时间】:2014-03-26 04:48:54
【问题描述】:
我在项目中有分层架构,例如 Controller -> Service -> DAO。我想为服务层编写 JUnit 测试用例。既然服务层会在内部调用DAO方法,我为什么要为DAO层编写不同的测试用例,因为它是内部测试的。
有人说我需要使用 mockito 来模拟 DAO 方法。真的需要吗?测试服务层方法时不能直接使用原代码吗?
【问题讨论】:
标签: unit-testing junit junit4
我在项目中有分层架构,例如 Controller -> Service -> DAO。我想为服务层编写 JUnit 测试用例。既然服务层会在内部调用DAO方法,我为什么要为DAO层编写不同的测试用例,因为它是内部测试的。
有人说我需要使用 mockito 来模拟 DAO 方法。真的需要吗?测试服务层方法时不能直接使用原代码吗?
【问题讨论】:
标签: unit-testing junit junit4
为您的服务提供一组测试,并为 DAO 提供一组单独的测试。
DAO 测试应该针对数据库,最好是内存数据库。这不仅仅是因为它很容易在测试中创建和拆除,而是因为你会知道它是你的,没有其他人会改变它。 DAO 测试将测试您的数据库映射和 SQL 是否正确。您可以使用 DBUnit 使用测试数据初始化数据库,并在每次测试结束时验证数据库的内容,因此每个测试都可以针对已知数据集运行。如果存在数据库级别的问题,则使用单独的 DAO 测试将更容易区分,因为您将在 DAO 测试中看到它们,而不是在服务测试中。
可以使用 DAO 的模拟来测试服务。因为测试不使用数据库,所以它们执行得更快(针对数据库的测试运行速度要慢得多,即使使用内存数据库也是如此),并且您可以在不减慢测试速度的情况下练习许多不同的场景。服务层通常是您最复杂的地方,因此需要更多测试来覆盖它,如果这些测试能够快速运行会更好。
通常情况下,您的 DAO 具有执行粗略操作的方法,并且这些方法在服务中以不同的方式被一遍又一遍地调用。当您将数据库访问限制为仅 DAO 测试时,您可以最大限度地减少测试所需的数据库访问总量,并且测试运行得更快。
您所说的,有一组测试一直针对数据库(服务和 DAO)进行测试,这非常诱人,因为 a) 它一直针对真实事物进行测试,并且 b) 看起来像它会减少工作量(很多时候项目没有足够的抽象,你不能有效地单独测试东西,也没有时间把事情搞砸)。许多项目出于合理的原因做出相同的决定,并且它们都直接进入了相同的测试陷阱,这些测试需要很长时间才能运行并且会留下太多的案例(因为开发人员在现有测试时不愿意添加更多的测试案例)已经花费了太长时间)。缓慢的测试会导致糟糕的代码覆盖率和无效的测试。
【讨论】:
在我看来,您应该尽可能避免使用 Mocks。避免使用 Mocks 的原因是:
这并不意味着您永远不应该使用 Mocks,但您应该尽可能地喜欢真正的实现。
另一方面,每当一个实现需要重量级的实现或数据库、JNDI 或 JMS 等资源时,您都想使用 Mocks。否则,您的测试始终是一种集成测试,需要重量级的设置并减慢您的测试套件。
我的建议是为每种需要重量级资源(如数据库、JNDI、JMS 等)的类型提供内存实现。为确保它们是真正的替代品,符合合同要求,它们必须通过与实际实现相同的测试.因此,必须对这些合同的实现进行全面的测试覆盖!
从现在开始,您应该可以在需要的地方使用真正的实现。对于所有难以测试的情况,例如网络错误、数据库连接或协议,我们使用 Mocks。它们在这种情况下是最好的,但仅在我看来应该简化为这些情况。
【讨论】: