为什么要避免使用Mockito.verify



我的公司不允许在单元测试中使用Mockito.verify。甚至还有一个自定义的声纳规则。
规则如下
应该通过断言来验证结果,而不是使用verify来进行流程验证。因为如果我们验证流程,在流程更改后需要更多的精力来维护测试,但输入和输出保持不变。确保每一行代码都对结果有影响,并断言结果以证明逻辑是正确的
不符合代码示例

verify(graphics2D, times(1)).dispose();// Noncompliant

符合要求的解决方案

assertThat(((SunGraphics2D) graphics2D).getSurfaceData()).isInstanceOf(NullSurfaceData.class);

对于数据库或中间件操作,使用嵌入式数据库或中间件断言数据写入成功。

对于restful请求,使用wiremock的verify来断言mock服务器收到了相应的请求

WireMock.verify(postRequestedFor(urlEqualTo("http://localhost:8080/query"))
.withHeader("Content-Type", equalTo("application/json"))
.withRequestBody(equalToJson("{" +
""testing-library": "WireMock"," +
""creator": "Tom Akehurst"," +
""website": "wiremock.org"" +
"}")));

我的问题是,是否有其他IT公司有类似的规则来避免在单元测试中使用Mockito.verify?这是一条好规则还是一条坏规则?非常感谢。

好吧,这需要一个长答案,但我会尽量缩短它。更换公司。这基本上是两种不同类型的测试。在一种情况下,您正在检查输入和输出(assert(,在另一种情况中,您的输出很可能是空的,然后您只需验证是否调用了该函数。

除此之外,您使用verify表示";集成测试";其中您想要验证函数是否被调用,并且您可能想要验证它们被调用的顺序;inOrder(("如下所述:Mockito验证方法调用的顺序

有时单元测试和集成测试重叠。整合测试有两种亚型:

  • 那些因为必要而需要模拟的人
  • 那些根本不使用mock的人

最近使用了一个maven插件,它允许在测试或验证阶段随意生成docker容器。

<groupId>io.fabric8</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>0.33.0</version>

这允许您在公共Jenkins管道中运行项目中的集成测试和端到端测试。当您无法在Jenkins中使用docker时,唯一的问题就会出现,因为运行测试的机器上没有安装docker。

没有验证的断言只能在测试方法返回后检查结束状态。为了有一个完整的结束状态,你需要有所有的真实对象,没有mock。任何正在使用的mock都意味着你最后没有一个完整的状态,并且你不能在不使用verify的情况下检查所有应该检查的内容。所以,如果禁止使用verify,那么您根本不应该使用Mockito。您应该意识到,您编写的是集成测试,而不是单元测试。

然而,集成测试不会告诉你哪里出了问题,以及在哪里寻找根本原因:错误是在你的代码中还是在你使用的第三方库的代码中?你必须调查和调试自己才能找到答案。这就是为什么你需要真正的单元测试。

如果被测试的方法需要进行单元测试,这意味着测试应该测试该方法正在做什么,而不依赖于被调用的任何方法的实现。当被调用的方法在mock中时,发送到mock的数据通常不在任何位置,并且您无法验证调用中是否传递了正确的数据。您可以使用存储参数的answer对象来存根该方法,然后断言它们。但是,您只是在使用assert实现自己的验证方法。当被调用的方法不是mock时,您的测试将取决于该方法的实现,不再是单元测试。更改被调用方法的实现可能会破坏许多正在调用该方法的方法的单元测试。

简而言之:如果你的公司不希望你使用verify,他们不希望你编写单元测试,而是集成测试。

单元测试和集成测试都是有用的,并且相互补充。如果结构良好,两者都是可维护的。但是,当您混合使用这两种类型时,测试变得很难维护(使用真实对象而不是mock的单元测试或使用mock的集成测试(。因此,对于集成测试,避免验证(和mock(是一条很好的规则。对于单元测试来说,这是一条糟糕的规则,因为它使编写真正的单元测试变得不可能。

最新更新