自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());
}
UUID.fromString(StaticMockTest.getUUIDValue());
}
public static String getUUIDValue() {
return UUID.randomUUID().toString();
}
}
之前的回答,可能是使用Mockito 1.x/2.x和Powermock 1.x/2.x
你可以像在真实实例上一样使用Mockito进行设置。例如,你可以链接存根,以下一行代码将使第一个调用不做任何操作,然后对getResources
的第二个及以后的调用将引发异常:
doNothing().doThrow(Exception.class).when(StaticResource.class);
StaticResource.getResource("string");
StaticResource.getResource("string");
StaticResource.getResource("string");
感谢Matt Lachman的一句话提醒,注意如果在模拟创建时未更改默认答案,则模拟默认情况下不会执行任何操作。因此,编写以下代码等效于不编写它。
doNothing().doThrow(Exception.class).when(StaticResource.class);
StaticResource.getResource("string");
尽管如此,对于将要读取测试的同事来说,您期望在这个特定的代码中什么也不期望会是有趣的。当然,这取决于测试的可理解性,可以进行相应的调整。
顺便说一下,在我看来,如果你正在编写新代码,应该避免模拟静态代码。在 Mockito 中,我们认为这通常是糟糕设计的提示,可能导致难以维护的代码。不过,对于现有的遗留代码来说,又是另一回事。
一般来说,如果需要模拟私有或静态方法,则表示该方法做了太多的事情,并且应该将其外部化为一个对象,该对象将被注入到测试对象中。
希望能对您有所帮助。
敬礼