Powermock验证静态方法中的私有静态方法调用

时间:2019-03-05 00:04:58

标签: java unit-testing powermock powermockito

我想知道是否有一种方法可以验证并调用为从测试中的公共静态方法调用的私有静态方法创建的模拟程序。

这是我正在测试的公共静态方法

public static String methodUnderTest(String p1){
   return privateStaticMethod(p1);
}

private static String privateStaticMethod(String p1){
        return "dummy";
}

我使用powermokito模拟了如下的私有静态方法:

@RunWith(PowerMockRunner.class)
@PrepareForTest(fullyQualifiedNames = "ClassUnderTest")
public class ClassUnderTestTest {

    @Test
    public void test_sometest() throws Exception {
         PowerMockito.spy(ClassUnderTest.class);

         PowerMockito.doReturn("whatever").when(ClassUnderTest.class, "privateStaticMethod","something");

         String retValue =  ClassUnderTest.methodUnderTest("something");  
         assertEquals(retValue, "whatever");            
    }
}

现在,有没有一种方法可以验证是否调用了privateStaticMethod?

1 个答案:

答案 0 :(得分:1)

事实证明确实很复杂。

如果可以解决问题,则解决方案可能会遵循here所写内容。不幸的是,我没有PowerMockito设置,所以我自己无法测试此代码:

asyncfunction

上面的代码使用Hamcrest // tell powermock(ito) that you want to do PARTIAL static mocking PowerMockito.spy(ClassUnderTest.class); // give it the mocking SPEC for that static method that needs mocking PowerMockito.doReturn("whatever").when(ClassUnderTest.class, "privateStaticMethod","something"); // tell it to INVOKE the real method when the public one is called PowerMockito.doCallRealMethod().when(Util, "methodUnderTest", any()); // now assert that the mock spec kicked in assertThat(ClassUnderTest.methodUnderTest("something"), is("whatever")); 匹配器,而is()将是(Power)Mockito参数匹配器。确保导入正确!

当您更改公用方法并且不调用该私有方法和/或返回其他内容时,以上操作将失败。

但真正的答案是:您应该避免这种测试。上面的代码隐式验证此私有方法已被调用:如果未调用该私有方法,您将收到不同的结果!

但是这里的重点是:您不应该测试这种东西。 如何公开方法如何获得结果与您的测试完全无关。您的公共方法有一个合同,如何实现它是实现 detail

您的方法将单元测试变成生产代码的(过于复杂!)重新实现。这意味着:您打算更改实施的第二次测试就需要调整。更糟糕的是,因为您将方法名称作为原始字符串传递,所以您甚至不会注意到,直到运行时,该方法突然停止返回any(),而给您whatever

所以,这里的 real 答案是:

  • 首先尽可能避免使用静态方法,因此您无需从事模拟静态方法的工作
  • 省去测试这样的实现细节。

毫无意义以验证是否调用了私有方法。您的公共方法的调用者应该返回“什么进来,什么回来”的信息。在该级别上,其他任何内容都无关紧要。

给出OP的评论:

  • 存在更多的静态问题,而不仅仅是“状态”。它杀死了多态性,也导致了对静态代码所在类的直接,硬性依赖
  • 这不仅使单元测试更加困难,而且任何类型的测试也变得更加困难
  • 以及我的亲身经历:当人们告诉我“我的新编写的代码需要PowerMock(ito)”时,我知道,他们无需进行任何操作即可创建难以测试的代码所以。绝对有可能(并且很希望)以可以用较少侵入性的模拟框架很好地测试的方式编写生产代码。

换句话说:如果您不能在Mockito中编写简单的直接测试,那么最有可能您创建了难以测试的生产代码,那么花时间和精力来做会更好。使生产代码更易于测试的精力。不必使用PowerMock(ito)锤通过解决症状来“解决”您的问题。是的,这很重要。我们来自基于PowerMock的“太多静态”代码库,只是在某个时候告诉人们“不再”。从那时起,当我们需要模拟时,我们使用Mockito。由于在不同地方“更改为静态”而导致的离奇的“单元测试失败”的数量减少到了0。我们的生产代码变得更好了。