Mockito 验证是否只调用了预期的方法编辑 #1

2022-09-02 03:57:44

我正在一个项目中工作,有一个类和某种作为门面的类(不知道这在设计模式的世界中是否是正确的术语,但我会试着让自己清楚)。的方法可能非常昂贵,因为它们可能与一个或多个数据库通信,长时间检查等,因此每个方法都应该调用一个且只有一个方法。ServiceClientServiceClientService

Service类结构类似于

public class Service {
    public void serviceA(){...}
    public SomeObject serviceB(){...}
    // can grow in the future
}

并且应该是这样的Client

public class Client {
    private Service myService; // Injected somehow
    public void callServiceA() {
        // some preparation
        myService.serviceA();
        // something else
    }

    public boolean callServiceB(){...}
}

在测试课上,我想有这样的东西Client

public class ClientTest{
    private Client client; // Injected or instantiated in @Before method
    private Service serviceMock = mock(Service.class);

    @Test
    public void callServiceA_onlyCallsServiceA() {
        client.callServiceA();
        ????
    }
}

在本节中,我想要这样的话:“验证 serviceMock.serviceA() 只被调用一次,并且没有调用 Service 类中的其他方法”。在Mockito或其他模拟库中是否有类似的东西?我不想使用每种方法,因为正如我所说,将来类可能会增长,我必须在每次测试中添加验证(对我来说不是一个快乐的任务),所以我需要一些更通用的东西。????verifyOnly(serviceMock).serviceA()verify(serviceMock, never()).serviceXXX()Service

提前感谢您的回答。

编辑 #1

这篇文章和可能的重复之间的区别在于,答案添加了在我的情况下不需要的样板代码,因为这是一个非常大的项目,我必须尽可能少地添加代码。

此外,verifyNoMoreInteractions可能是一个不错的选择,即使它不鼓励用于每个测试,也不需要额外的样板代码。

总而言之,可能的重复并没有解决我的问题。

还有另一个问题:我正在为另一个团队编写的代码编写测试,而不是自己遵循TDD程序,所以我的测试应该是额外的防御性的,正如本文中引用的mockito文档中所述。我正在测试的方法通常很长,所以我需要检查所测试的方法是否只调用必要的服务,而不调用其他服务(因为它们很昂贵,正如我所说)。也许现在已经足够好了,但我希望看到同一个API创建团队在每次测试中都不气馁!verifyNoMoreInteractions

希望这有助于澄清我的观点和问题。此致敬意。


答案 1
verify(serviceMock, times(1)).serviceA();
verifyNoMoreInteractions(serviceMock);

来自 Mockito 的 javadoc on verifyNoMoreInteractions

您可以在验证模拟后使用此方法 - 以确保在模拟上未调用任何其他内容。

也:

警告一句:一些做了很多经典的,期望运行验证模拟的用户倾向于经常使用verifyNoMoreInteractions(),即使在每种测试方法中也是如此。verifyNoMoreInteractions() 不建议在每个测试方法中使用。verifyNoMoreInteractions() 是交互测试工具包中一个方便的断言。仅当相关时才使用它。滥用它会导致过度指定,维护性较差的测试。


答案 2

可靠地验证服务是否只从指定的方法调用一次且仅调用一次而不是从任何其他方法调用的唯一方法是测试每个方法并断言永远不会调用您的方法。但是无论如何,您正在测试所有其他方法,因此这不应该是太大的提升......serviceA

// In other test cases...
verify(serviceMock, never()).serviceA();

虽然从代码编写的角度来看,这是不可取的,但它打开了将服务分离成更小、更负责任的块的大门,以便保证只调用一个特定的服务。从那里开始,围绕代码的测试用例和保证变得更小,更铁板钉钉。


推荐