spring 使用Mockito模拟静态void方法,mockStatic()

6jygbczu  于 2023-08-02  发布在  Spring
关注(0)|答案(2)|浏览(164)

我正在使用Sping Boot ,在我的一个单元测试中,我需要模拟Files.delete(somePath)函数。它是一个静态void方法。
我知道使用Mockito可以模拟void方法:

doNothing().when(MyClass.class).myVoidMethod()

字符串
自2020年7月10日起,可以模拟静态方法:

try (MockedStatic<MyStaticClass> mockedStaticClass = Mockito.mockStatic(MyStaticClass.class)) {
    mockedStaticClass.when(MyStaticClass::giveMeANumber).thenReturn(1L);
    assertThat(MyStaticClass.giveMeANumber()).isEqualTo(1L);
  }


但是我无法模拟像Files.delete(somePath)这样的静态void方法。
这是我的pom.xml文件(仅测试相关的依赖项):

<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-inline</artifactId>
    <version>3.5.15</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-core</artifactId>
    <version>3.5.15</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-junit-jupiter</artifactId>
    <version>3.5.15</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
    <version>2.2.6.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-test</artifactId>
    <scope>test</scope>
</dependency>


有没有一种方法可以在不使用PowerMockito的情况下模拟静态void方法?
如果可能的话,那么这样做的正确语法是什么?

uz75evzq

uz75evzq1#

通常,模拟静态调用是最后的手段,这不应该被用作默认方法。
例如,对于测试代码,与文件系统一起工作,有更好的方法。例如,根据junit版本,使用TemporaryFolder rule@TempDir annotation
此外,请注意,Mockito.mockStatic可能会显著减慢您的测试速度(例如:看下面的笔记)。
说了上面的警告,找到下面的代码片段,它展示了如何测试,该文件被删除了。

class FileRemover {
    public static void deleteFile(Path filePath) throws IOException {
        Files.delete(filePath);
    }
}

class FileRemoverTest {

    @TempDir
    Path directory;

    @Test
    void fileIsRemovedWithTemporaryDirectory() throws IOException {
        Path fileToDelete = directory.resolve("fileToDelete");
        Files.createFile(fileToDelete);

        FileRemover.deleteFile(fileToDelete);

        assertFalse(Files.exists(fileToDelete));
    }

    @Test
    void fileIsRemovedWithMockStatic() throws IOException {
        Path fileToDelete = Paths.get("fileToDelete");
        try (MockedStatic<Files> removerMock = Mockito.mockStatic(Files.class)) {
            removerMock.when(() -> Files.delete(fileToDelete)).thenAnswer((Answer<Void>) invocation -> null);
            // alternatively
            // removerMock.when(() -> Files.delete(fileToDelete)).thenAnswer(Answers.RETURNS_DEFAULTS);

            FileRemover.deleteFile(fileToDelete);

            removerMock.verify(() -> Files.delete(fileToDelete));
        }
    }
}

字符串

备注:

  1. Mockito.mockStatic在Mockito 3.4及以上版本中可用,请检查您使用的是正确的版本。
    1.该代码片段特意展示了两种方法:@TempDirMockito.mockStatic。当运行这两个测试时,你会注意到Mockito.mockStatic要慢得多。例如,在我的系统测试中,使用Mockito.mockStatic运行大约900毫秒,而@TempDir运行10毫秒。
dxxyhpgq

dxxyhpgq2#

使用mockStatic,然后在返回的示例中指定mock。

try (MockedStatic<Files> mockFiles = Mockito.mockStatic(Files.class)) {
    mockFiles.when(() -> Files.delete(anyString()))
                     .then(invocationOnMock -> null);
}

字符串

相关问题