Mockito 使用 Mockito.mockStatic() 模拟静态 void 方法
Mockito Mock a static void method with Mockito.mockStatic()
我正在使用 Spring Boot,在我的一个单元测试中,我需要模拟 Files.delete(somePath)
函数。这是一个静态无效方法。
我知道使用 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)
。
这是我的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 的情况下模拟 static void 方法?
如果可能的话,正确的语法是什么?
一般来说,模拟静态调用是最后的手段,不应用作默认方法。
例如,对于与文件系统一起工作的代码的测试,有更好的方法。例如。根据 junit
版本使用 TemporaryFolder
rule or @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));
}
}
}
备注:
Mockito.mockStatic
在 Mockito 3.4 及更高版本中可用,因此请检查您使用的版本是否正确。
该片段故意显示了两种方法:@TempDir
和 Mockito.mockStatic
。当 运行 两个测试时,您会注意到 Mockito.mockStatic
慢得多。例如。在我的系统测试中 Mockito.mockStatic
运行s 大约 900 毫秒 vs @TempDir
.
10 毫秒
我正在使用 Spring Boot,在我的一个单元测试中,我需要模拟 Files.delete(somePath)
函数。这是一个静态无效方法。
我知道使用 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)
。
这是我的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 的情况下模拟 static void 方法?
如果可能的话,正确的语法是什么?
一般来说,模拟静态调用是最后的手段,不应用作默认方法。
例如,对于与文件系统一起工作的代码的测试,有更好的方法。例如。根据 junit
版本使用 TemporaryFolder
rule or @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));
}
}
}
备注:
Mockito.mockStatic
在 Mockito 3.4 及更高版本中可用,因此请检查您使用的版本是否正确。该片段故意显示了两种方法:
10 毫秒@TempDir
和Mockito.mockStatic
。当 运行 两个测试时,您会注意到Mockito.mockStatic
慢得多。例如。在我的系统测试中Mockito.mockStatic
运行s 大约 900 毫秒 vs@TempDir
.