Junit5 模拟一个静态方法

Junit5 mock a static method

我想在 JUnit 5. But unfortunately, JUnit 5 doesn’t support Mockito 中模拟一个静态方法。除了恢复到 JUnit 4 之外,还有其他方法可以实现同样的效果吗?

Mockito 目前不提供静态方法模拟的原因是因为人们普遍认为静态方法不需要被模拟。

但是,有一个 Mockito here 的开放项目讨论了这个问题。

虽然这不能回答您的问题,但总的来说它会告诉您为什么您根本不需要该功能或允许您加入对话并提出您的想法。

简短的回答是否定的,因为 Mockito 团队已经完成了他们的 work and is waiting for the JUnit team for an extension 并且正在这里进行大量讨论。

只需一些开销,您就可以:由于 JUnit 5 提供了对 运行 遗留 JUnit 4 的支持,因此您可以使用 Mockito。因此,您可以在 Junit4 中为这些情况创建测试:

使用 Mockito 2 gradle and with mvn. From there I am using PowerMock 2.0 beta 进行迁移设置的示例项目。

从 Mockito 3.4.0 (2020-07-10) 开始,即使在 JUnit 5 中也可以开箱即用地模拟静态方法,无需任何扩展。

在文档中,您可以找到一个示例:48. Mocking static methods (since 3.4.0)

重要说明:您需要使用内联模拟生成器。所以要用的依赖不是核心的:

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

示例: Class 正在测试中:

package teststatics;

public class FooWithStatics {
    public static Long noParameters() {
        return System.currentTimeMillis();
    }
    public static String oneParameter(String param1) {
        return param1.toUpperCase();
    }
}

测试class:

package teststatics;

import org.junit.jupiter.api.Test;
import org.mockito.MockedStatic;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;

public class FooWithStaticsTest {

    @Test
    void testStatic() {
        // Before mock scope, usual behavior.
        assertNotEquals(0L, FooWithStatics.noParameters());
        assertNotEquals("yyy", FooWithStatics.oneParameter("xxx"));

        // Mock scope
        try (MockedStatic mocked = mockStatic(FooWithStatics.class)) {

            // Mocking
            mocked.when(FooWithStatics::noParameters).thenReturn(0L);
            mocked.when(() -> FooWithStatics.oneParameter("xxx")).thenReturn("yyy");

            // Mocked behavior
            assertEquals(0L, FooWithStatics.noParameters());
            assertEquals("yyy", FooWithStatics.oneParameter("xxx"));

            // Verifying mocks.
            mocked.verify(times(1), FooWithStatics::noParameters);
            mocked.verify(times(1), () -> FooWithStatics.oneParameter("xxx"));
        }

        // After mock scope returns to usual behavior.
        assertNotEquals(0L, FooWithStatics.noParameters());
        assertNotEquals("yyy", FooWithStatics.oneParameter("xxx"));
    }
}
  1. 确保在您的 POM 文件中有 mockito-inline 依赖项

    <dependency>
        <groupId>org.mockito</groupId>
        <artifactId>mockito-inline</artifactId>
        <version>3.6.28</version>
        <scope>test</scope>
    </dependency>
    
  2. 在我的例子中,我不得不测试 URLEncoder Class 的静态方法 encode() 异常抛出的场景,所以

    try (MockedStatic theMock  = mockStatic(URLEncoder.class)) {
        theMock.when(() -> URLEncoder.encode("Test/11", StandardCharsets.UTF_8.toString()))
        .thenThrow(UnsupportedEncodingException.class);
        when(restClient.retrieveByName("Test%2F11")).thenReturn(null);
        Assertions.assertThrows(ResponseStatusException.class, ()->service.retrieveByName("Test/11"));
    }