这是个好问题!我认为它的根本原因如下,我们不仅使用 JUnit 进行单元测试。所以这个问题应该分开:
- 我应该在集成(或任何其他高于单元测试)测试中使用 Mockito.verify() 吗?
- 我应该在黑盒单元测试中使用 Mockito.verify() 吗?
- 我应该在白盒单元测试中使用 Mockito.verify() 吗?
所以如果我们忽略高于单元测试,这个问题可以改写为“使用带有 Mockito.verify() 的白盒单元测试在单元测试和我的可能实现之间创建了很好的一对,我可以做一些“灰盒“单元测试以及我应该使用什么经验法则”。
现在,让我们一步一步地完成所有这些。
*- 我应该在我的集成(或任何其他高于单元测试)测试中使用 Mockito.verify() 吗?* 我认为答案显然是否定的,而且你不应该为此使用模拟。您的测试应尽可能接近实际应用。您正在测试完整的用例,而不是应用程序的孤立部分。
*黑盒与白盒单元测试* 如果您使用黑盒方法,您真正在做什么,您提供(所有等价类)输入、状态和测试,您将收到预期的输出。在这种方法中,使用模拟通常是合理的(您只是模仿他们正在做正确的事情;您不想测试它们),但是调用 Mockito.verify() 是多余的。
如果您使用的是白盒方法,那么您正在测试您的单元的行为。在这种方法中调用 Mockito.verify() 是必不可少的,您应该验证您的单元的行为是否符合您的预期。
灰盒测试的经验法则 白盒测试
的问题在于它会产生高耦合。一种可能的解决方案是进行灰盒测试,而不是白盒测试。这是一种黑白盒测试的组合。你真的在测试你的单元的行为,就像在白盒测试中一样,但一般来说,你尽可能让它与实现无关。如果可能,您只需像在黑盒情况下一样进行检查,只需断言输出是您所期望的。所以,你的问题的本质是什么时候可能。
这真的很难。我没有很好的例子,但我可以给你举个例子。在上面提到的 equals() 与 equalsIgnoreCase() 的情况下,您不应该调用 Mockito.verify(),只需断言输出即可。如果你做不到,把你的代码分解成更小的单元,直到你能做到为止。另一方面,假设您有一些@Service,并且您正在编写@Web-Service,它本质上是@Service 的包装器——它将所有调用委托给@Service(并进行一些额外的错误处理)。在这种情况下,调用 Mockito.verify() 是必不可少的,你不应该重复你对@Serive 所做的所有检查,验证你使用正确的参数列表调用@Service 就足够了。