首页 > 解决方案 > 当调用多个静态方法时,使用 Mockito 验证静态方法调用

问题描述

我正在尝试验证在测试期间是否调用了静态方法。但是,由于在运行期间调用了同一类的多个静态方法,因此它会引发异常。这两种静态方法都是模拟的。确切的例外是这样的:-

验证静态存根时发生意外错误。

要正确验证存根,请在提供的 lambda 中调用 com.booking.capacityservicejobs.models.YourStaticClass 的单个静态方法。

例如,如果定义了方法“sample”,请提供包含代码的 lambda 或匿名类。

代码是这样的: -

try (MockedStatic<MyClass1> theMock = Mockito.mockStatic(MyClass1.class);
    MockedStatic<MyClass2> configMock = Mockito.mockStatic(MyClass2.class);
    MockedStatic<MyClass3> downtimeMock = Mockito.mockStatic(MyClass3.class)) {
        theMock.when(MyClass1::lockAndFetch).thenReturn(duRuns);
        theMock.when(() -> MyClass1.startAndUnlock(1)).thenAnswer(invocation -> null);
        configMock.when(() -> MyClass2.getById(1)).thenReturn(dummyConfig);
        downtimeMock.when(() -> MyClass3.isScheduledForRole("app-dummy")).thenReturn(false);
        new RunExecutor().run(); //this executes the code to be tested

        theMock.verify(() -> MyClass1.startAndUnlock(1));
    }

我可以在不使用 powermock 的情况下绕过这个限制吗?验证多个(不同)静态方法调用的正确方法是什么?

标签: javatestingmockito

解决方案


即使我同意这不是一个好的做法,我也不得不自己处理这个问题,因为我对库中的静态实用程序类有依赖关系,我无法重构它,所以我的答案是这样。

我的情况与您的情况不完全一样:我正在测试一个方法,该方法HttpUtils.logProtocolMessages内部调用了LoggingApi实用程序类中的 2 个不同的静态方法;两种方法都返回无效。这对我有用:

@Test
public void logProtocolMessageWithoutRequestTest() {

    try (MockedStatic<LoggingApi> mockLog = Mockito.mockLog(LoggingApi.class)){
        mockLog.when(() -> {
            LoggingApi.setProtocolSendMessage(anyString(), anyString());
            LoggingApi.setProtocolReceiveMessage(anyString(), anyString(), anyString());
        }).thenAnswer(Answers.RETURNS_DEFAULTS);
        
        HttpUtils.logProtocolMessages(mockTarget, HttpClientVersion.HTTP_2, response, null);
        
        mockLog .verify(() -> JcatLoggingApi.setProtocolSendMessage(anyString(), anyString()));
        mockLog .verify(() -> LoggingApi.setProtocolReceiveMessage(anyString(), anyString(), anyString()));
    }
}

如您所见,这 2 个静态方法在同一个 lambda 中被模拟,它们都被指示不返回任何内容。我想说,任何超出此范围的案例都应该考虑重新设计(如果可能的话),甚至是测试本身。

这仅适用于使用 verify 的基本验证,例如调用模拟方法的 # 次。如果您尝试进行更复杂的检查,例如捕获参数,则在 lambda 中调用单个静态方法的限制将占上风,并且任何基于捕获者的断言都将失败,因为 Mockito 无法在多个时正确注入它们的值调用同一模拟静态类中的方法。

这是我使用的模拟依赖项:

<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-inline</artifactId>
    <version>4.1.0</version>
    <scope>test</scope>
</dependency>

推荐阅读