从 Mockito 3.4.0 开始,引入了一个实验性 API 来模拟静态方法。
以下示例代码已使用 Mockito 4.3.1 ( testImplementation("org.mockito:mockito-inline:4.3.1
) 和 JUnit Jupiter 5.8.2、OpenJDK 11 进行了测试。
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import java.util.UUID;
public class StaticMockTest {
@Test
void showCaseStaticMock() {
try (MockedStatic<StaticMockTest> staticMock = Mockito.mockStatic(StaticMockTest.class)) {
staticMock.when(StaticMockTest::getUUIDValue).thenReturn("Mockito");
Assertions.assertEquals("Mockito", StaticMockTest.getUUIDValue());
}
// Regular UUID
UUID.fromString(StaticMockTest.getUUIDValue());
}
public static String getUUIDValue() {
return UUID.randomUUID().toString();
}
}
上一个答案,可能是 Mockito 1.x/2.x 和 Powermock 1.x/2.x
您可以像在真实实例上使用 Mockito 一样进行操作。例如,您可以链接存根,以下行将使第一次调用什么也不做,然后第二次和将来的调用getResources
将抛出异常:
// the stub of the static method
doNothing().doThrow(Exception.class).when(StaticResource.class);
StaticResource.getResource("string");
// the use of the mocked static code
StaticResource.getResource("string"); // do nothing
StaticResource.getResource("string"); // throw Exception
感谢 Matt Lachman 的评论,请注意,如果在创建模拟时没有更改默认答案,则模拟默认情况下不会执行任何操作。因此写下面的代码相当于不写。
doNothing().doThrow(Exception.class).when(StaticResource.class);
StaticResource.getResource("string");
尽管如此,对于阅读测试的同事来说,您对这个特定代码没有任何期望可能会很有趣。当然,这可以根据测试的可理解性进行调整。
顺便说一句,以我的拙见,如果您编写新代码,您应该避免模拟静态代码。在 Mockito,我们认为这通常暗示着糟糕的设计,它可能导致代码可维护性差。尽管现有的遗留代码是另一回事。
一般来说,如果你需要模拟私有或静态方法,那么这个方法做的太多了,应该外化在一个对象中,然后注入到测试对象中。
希望有帮助。
问候