如何使用 Mockito 在类中只模拟一个静态方法?

Kum*_*mar 9 java unit-testing mockito

以下行似乎模拟了类中的所有静态方法:

MockedStatic <Sample> sampleMock = Mockito.mockStatic( Sample.class );
sampleMock.when( () -> Sample.sampleStaticMethod( Mockito.any( String.class ) ) ).thenReturn( "response" );
Run Code Online (Sandbox Code Playgroud)

是否可以只模拟一个类中的一个静态方法?

Mar*_*arc 13

默认情况下,所有方法都是模拟的。但是,使用Mockito.CALLS_REAL_METHODS您可以配置模拟以实际触发真正的方法,仅排除一种。

例如给定的类Sample

class Sample{
    static String method1(String s) {
        return s;
    }
    static String method2(String s) {
        return s;
    }
}
Run Code Online (Sandbox Code Playgroud)

如果我们只想模拟method1

@Test
public void singleStaticMethodTest(){
    try (MockedStatic<Sample> mocked = Mockito.mockStatic(Sample.class,Mockito.CALLS_REAL_METHODS)) {
        mocked.when(() -> Sample.method1(anyString())).thenReturn("bar");
        assertEquals("bar", Sample.method1("foo")); // mocked
        assertEquals("foo", Sample.method2("foo")); // not mocked
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,realSample.method1()仍然会被调用。从Mockito.CALLS_REAL_METHODS文档:

在处理遗留代码时,此实现会很有帮助。使用此实现时,未存根的方法将委托给真正的实现。这是一种创建默认调用真实方法的部分模拟对象的方法。...

注 1:使用when(mock.getSomething()).thenReturn(fakeValue)语法存根部分模拟 将调用真正的方法。对于部分模拟,建议使用doReturn 语法。

因此,如果您根本不想触发存根静态方法,则解决方案是使用语法doReturn(如文档所建议的那样),但仍然不支持静态方法:

@Test
public void singleStaticMethodTest() {
    try (MockedStatic<Sample> mocked = Mockito.mockStatic(Sample.class,Mockito.CALLS_REAL_METHODS)) {
        doReturn("bar").when(mocked).method1(anyString()); // Compilation error!
        //...
    }
}
Run Code Online (Sandbox Code Playgroud)

关于这个有一个未解决的问题,特别检查这个评论

  • @Kumar这似乎是文档的预期行为(请参阅我更新的答案)。因此静态方法被存根但仍然被调用。现在的问题是如何对静态方法使用 doReturn 语法来确保不调用真正的存根方法。 (2认同)