首页 > 解决方案 > Mockito 验证对模拟对象的最后一次调用

问题描述

我有一些需要测试的逻辑,例如:

{
    ...
    A.add("1");
    ...
    A.add("what ever");
    ...
    A.add("2");
    A.delete("5");
    ...
}

我已经在我的测试中模拟了 A 并且我可以测试 add 方法在参数(“2”)上调用一次,例如:

Mockito.verify(mockedA).add("2");

我的问题是如何测试是否可以验证对方法 add 的最后调用是 add("2") 而不是其他参数。

由于上面的测试无法捕捉到是否有人在最后添加了另一个调用,例如 add("3")。请注意,之后我们不再关心 A 上的其他方法调用。我们也不关心方法调用的次数,方法调用的顺序。这里的关键点是我们是否可以验证某个 mockedObject 的某个方法上的最后一个 true 参数。

如果您问为什么需要这样的功能,我会说在现实世界中我们可能需要处理一些设置某些东西并且最后一组获胜的逻辑,并且为了避免有人意外设置其他一些意想不到的东西,我会喜欢用我们的 UT 来捕捉这个。而且为了不让测试过于复杂和整洁,所以我只希望验证对象的某个方法的最后一次调用,而不是验证诸如 order/noMoreInteractions/AtMostTimes 之类的东西。

标签: javamockitocallverify

解决方案


关于调用的顺序

默认情况下,Mockito.verify()调用顺序无关紧要。
考虑到这一点,将模拟包装在一个InOrder实例中并在该实例上执行调用验证。

关于没有更多的互动

如果在您要验证的方法之后不再调用模拟,您可以使用Mockito.verifyNoMoreInteractions(Object... mocks)它检查任何给定的模拟是否有任何未经验证的交互,例如:

InOrder inOrder = Mockito.inOrder(mockedA);
inOrder.verify(mockedA).add("1");
inOrder.verify(mockedA).add("2");
Mockito.verifyNoMoreInteractions(mockedA);

如果在您要验证的方法之后仍然可以调用模拟,您可以在验证调用之后添加,verify(T mock, VerificationMode mode)通过传递一个VerificationMode检查最多执行 2 次调用的方法。

InOrder inOrder = Mockito.inOrder(mockedA);
inOrder.verify(mockedA).add("1");
inOrder.verify(mockedA).add("2");
Mockito.verify(mockedA, Mockito.atMost(2)).add(Mockito.anyString());

关于你的想法和这种嘲笑方式的警告

由于上面的测试无法捕捉到是否有人在最后添加了另一个调用,例如 add("3")。

Mockito 提供了一个强大而广泛的工具包来处理模拟。某些功能,例如验证,尤其是验证没有检测到关于模拟或模拟的特定方法的更多交互,使您的测试更难以阅读和维护
此外,目前您希望检查模拟上的调用是否按特定顺序执行。但是您通常只想根据业务/逻辑场景的需要使用这些检查,而不是技术调用。
例如,假设在测试方法中,由于业务原因,模拟方法被调用 3 次,另一种情况是模拟方法被调用 2 次。检查它是否只被调用了 2 次而不是在预期调用两次的情况下是有意义的。
但总的来说,您应该小心,您的单元测试不会过度使用模拟验证,这可能看起来像是对流程描述的断言,而不是对行为/逻辑的断言。


推荐阅读