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

How to mock just one static method in a class using Mockito?

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

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

是否可以在 class 中只模拟一个静态方法?

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

例如给定 class Sample:

class Sample{
    static String method1(String s) {
        return s;
    }
    static String method2(String s) {
        return s;
    }
}

如果我们只想模拟 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
    }
}

注意真正的Sample.method1()还是会被调用的。来自 Mockito.CALLS_REAL_METHODS 文档:

This implementation can be helpful when working with legacy code. When this implementation is used, unstubbed methods will delegate to the real implementation. This is a way to create a partial mock object that calls real methods by default. ...

Note 1: Stubbing partial mocks using when(mock.getSomething()).thenReturn(fakeValue) syntax will call the real method. For partial mock it's recommended to use doReturn syntax.

因此,如果您根本不想触发存根静态方法,解决方案是使用语法 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!
        //...
    }
}

关于这个有一个open issue, in particular check this comment