【问题标题】:PowerMock: mocking of static methods (+ return original values in some particular methods)PowerMock:模拟静态方法(+在某些特定方法中返回原始值)
【发布时间】:2011-02-01 08:42:54
【问题描述】:

我使用 PowerMock 1.4.7 和 JUnit 4.8.2

我只需要模拟一些静态方法并且我想要其他方法(来自 同一类)只是为了返回原始值。 当我用mockStatic 模拟并且不调用when().doReturn() all 静态方法返回它们的默认值——比如返回 Object 时为 null 或返回布尔值时为假...等。所以我尝试使用 thenCallRealMethod 在每个静态方法上显式返回 默认实现(意味着没有嘲笑/没有假货)但我不知道 如何在每个可能的参数变化上调用它(=我想要每个可能的输入调用原始方法)。我只知道如何模拟具体的参数变化。

【问题讨论】:

标签: java mocking mockito powermock


【解决方案1】:

您可以在静态类上使用间谍并仅模拟特定方法:

@RunWith(PowerMockRunner.class)
@PrepareForTest(MyStaticTest.MyStaticClass.class)
public class MyStaticTest {

public static class MyStaticClass {
    public static String getA(String a) {
        return a;
    }
    public static String getB(String b) {
        return b;
    }
}

@Test
public void should_partial_mock_static_class() throws Exception {
    //given
    PowerMockito.spy(MyStaticClass.class);
    given(MyStaticClass.getB(Mockito.anyString())).willReturn("B");
    //then
    assertEquals("A", MyStaticClass.getA("A"));
    assertEquals("B", MyStaticClass.getA("B"));
    assertEquals("C", MyStaticClass.getA("C"));
    assertEquals("B", MyStaticClass.getB("A"));
    assertEquals("B", MyStaticClass.getB("B"));
    assertEquals("B", MyStaticClass.getB("C"));
}

}

【讨论】:

  • 虽然这可行,但在使用匹配器参数时要小心。如果您要使用 Mockito.any() 并且您正在尝试存根间谍的方法,则在评估存根语句期间会调用实际的 getB() impl。如果 getB() 无法处理空参数,则会抛出 NPE。
  • 什么是“给定的”?
  • 这对我不起作用。我必须用 PowerMockito.mockStatic(...) 替换 .spy(..) 才能让它工作;这反驳了作者预期的解决方案。
  • 这对我不起作用,即使经过多次迭代,即使使用@LucianovanderVeekens cmets。请多解释一下?
【解决方案2】:

您也可以使用存根 API:

stub(method(MyStaticClass.class, "getB")).toReturn("B");

编辑:

要使用stub 和method 从这些包中静态导入方法:

  1. org.powermock.api.support.membermodification.MemberModifier
  2. org.powermock.api.support.membermodification.MemberMatcher

更多信息请参考documentation

【讨论】:

  • 这种方法对我有用,但 denis.soloenko 的回答没有。很难理解何时使用 doReturn、when、given 和 stub,它们都声称做同样的事情。每一种有时都有效,而另一些则无效
  • 这种方法在对静态类进行部分模拟时对我有用。
  • 谢谢,请添加stub方法范围
  • 你如何使用这个?您能否提供整个代码示例。
  • 我已经添加了关于从现在开始静态导入方法的包的说明
【解决方案3】:

我设法使用spy 和doReturn 来实现它。

class MyStatic {
    static String foo() { return "foo"; }
    static String foobar() { return foo() + "bar"; }
}

@Test
public void thisShouldSpyStaticMethods() {
    // arrange
    spy(MyStatic.class);
    doReturn("mocked foo").when(MyStatic.class);
    MyStatic.foo();

    // act
    final String result = MyStatic.foobar();

    // assert
    assertThat(result).isEqualTo("mocked foobar");
}

doReturn 之后调用要模拟的方法看起来很奇怪(至少对我而言),但似乎可以解决问题。

将spy 与when(MyStatic.foo()).thenReturn("mocked foo") 一起使用对我不起作用。

PowerMockito 在mocking static method 上的文档。

【讨论】:

  • 虽然这可行,但它不适用于一个方法调用中的多个静态方法。
【解决方案4】:

基于这个问题PowerMockito mock single static method and return object

PowerMockito.mockStatic(MyStaticClass.class);

单独不会模拟所有方法(至少在最新版本的 PowerMockito 中),只能在以后模拟单个方法。

【讨论】:

    猜你喜欢
    • 2019-10-28
    • 2012-03-24
    • 2016-04-23
    • 1970-01-01
    • 1970-01-01
    • 2014-02-03
    • 1970-01-01
    • 2021-12-31
    相关资源
    最近更新 更多