Mockito 如何 mock 静态方法
自 3.4.0,Mockito 提供了静态方法的 mocking 支持。
首先,你需要引入 mockito-inline
依赖(或者把 mockito-core
改成 mockito-inline
)。
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-inline</artifactId>
<version>4.3.1</version>
<scope>test</scope>
</dependency>
这里千万要注意使用 try-with-resource,MockedStatic 使用完之后需要关闭。
MockedStatic 继承了 AutoCloseable,可以通过 try-with-resource 自动关闭。
MockedStatic.when(...)
方法接收一个方法引用作为入参。如果是无参数的静态方法,可以直接用 Foo::method 的形式传递。
MockedStatic 关闭之后,mock 就会被恢复原状。
assertEquals("foo", Foo.method());
try (MockedStatic mocked = mockStatic(Foo.class)) {
mocked.when(Foo::method).thenReturn("bar");
assertEquals("bar", Foo.method());
mocked.verify(Foo::method);
}
assertEquals("foo", Foo.method());
代码基于 junit5 编写。
1. Mock 无参数的静态方法
@Test
void mockStaticMethodWithoutArgument() throws InterruptedException {
try (MockedStatic<LocalDateTime> mockedStatic = mockStatic(LocalDateTime.class)) {
mockedStatic.when(
() -> {
LocalDateTime.now();
})
.thenReturn(LocalDateTime.MIN);
assertEquals(LocalDateTime.now(), LocalDateTime.MIN);
}
}
2. Mock 有参数的静态方法
@Test
void mockStaticMethodWithArguments() throws InterruptedException {
try (MockedStatic<LocalDateTime> mockedStatic = mockStatic(LocalDateTime.class)) {
mockedStatic.when(
() -> {
LocalDateTime.parse("anyString");
})
.thenReturn(LocalDateTime.MIN);
assertEquals(LocalDateTime.parse("anyString"), LocalDateTime.MIN);
}
}
3. 使用 ArgumentMatcher
同样的,按照 Mockito 一贯的风格,我们同样可以使用 ArgumentMatcher 。
@Test
void mockStaticMethodWithArgumentsUsingArgumentMatcher() throws InterruptedException {
try (MockedStatic<LocalDateTime> mockedStatic = mockStatic(LocalDateTime.class)) {
mockedStatic.when(
() -> {
LocalDateTime.parse(anyString());
})
.thenReturn(LocalDateTime.MIN);
assertEquals(LocalDateTime.parse("anyString"), LocalDateTime.MIN);
assertEquals(LocalDateTime.parse("otherString"), LocalDateTime.MIN);
}
}
4. 校验静态方法调用
校验方法调用跟普通的 mocking 差不多。
mockedStatic.verify(() -> {LocalDateTime.now();});
mockedStatic.verify(() -> {LocalDateTime.now();}, times(2));
5. 获取实参
要获得静态方法调用时传入的参数,一样是老一套的 ArgumentCaptor。
ArgumentCaptor<String> argumentCaptor = ArgumentCaptor.forClass(String.class);
try (MockedStatic<LocalDateTime> mockedStatic = mockStatic(LocalDateTime.class)) {
mockedStatic.when(
() -> {
LocalDateTime.parse(argumentCaptor.capture());
})
.thenReturn(LocalDateTime.MIN);
LocalDateTime.parse("Hello, world!");
assertEquals("Hello, world!", argumentCaptor.getValue());
}