【问题标题】:How to mock just one static method in a class using Mockito?如何使用 Mockito 在一个类中模拟一个静态方法?
【发布时间】:2020-09-11 04:43:22
【问题描述】:

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

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

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

【问题讨论】:

  • 我更新了我的答案here 以包含更多我认为有助于解决此问题的信息
  • @KevinK,我尝试了您的示例,虽然该方法返回了它应该返回的内容,但它实际上被调用了,尽管被嘲笑了。这是预期的吗?您的样本中是否也发生过这种情况?
  • @Kumar 应该阅读文档。解决方案是使用 doReturn().when() 语法,但仍不受支持,请查看我的答案中的详细信息。

标签: java unit-testing mockito


【解决方案1】:

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

例如给定类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 文档:

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

注 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!
        //...
    }
}

关于这个有一个open issue,特别检查这个comment

【讨论】:

  • 你真的亲自尝试过这个方法吗?我试过了,它最终调用了被模拟的静态方法。让我在一个示例项目中尝试一下,而不是我现在使用的遗留项目。
  • 是的,我自己尝试过,使用我提供的 Sample 类。重现它应该不是问题。否则请告诉我。
  • 我试过了,模拟的方法返回了预期的响应。但我也注意到正在调用模拟方法(尽管响应是测试中指定的)。这是预期的吗?
  • @Kumar 这似乎是文档中的预期行为(请参阅我更新的答案)。所以静态方法被存根但仍然被调用。现在的问题是如何对静态方法使用doReturn 语法来确保不调用真正的存根方法。
  • ...但是,使用 Mockito.CALLS_REAL_METHODS 您可以将模拟配置为实际触发实际方法...当您想使用其内部测试实际方法时,请使用 @spy
猜你喜欢
  • 2015-10-14
  • 2021-11-19
  • 2013-01-08
  • 2018-02-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-30
相关资源
最近更新 更多