当前位置: 首页 > 知识库问答 >
问题:

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

尉迟京
2023-03-14

我想知道是否有一种方法来验证和调用一个模拟,该模拟是为一个私有静态方法创建的,该私有静态方法是从一个被测试的公共静态方法调用的。

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

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");            
    }
}

共有1个答案

杭胜
2023-03-14

结果是真的很复杂。

如果这能起作用,那么解决方案可能会按照上面所写的进行。不幸的是,我没有PowerMockito设置,所以我不能自己测试这段代码:

// 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"));

上面使用了HamcrestIS()匹配器,而any()将是一个(幂)Mockito参数匹配器。确保输入正确!

当您更改公共方法而不调用该私有方法,和/或返回其他方法时,上述操作将失败。

但真正的答案是:你应该避免这样的测试。上面的代码隐式验证了是否调用了这个私有方法:如果没有调用它,您应该会收到一个不同的结果!

但这里真正的重点是:你不应该测试这样的东西。您的公共方法如何得到它的结果对您的测试不应该有任何影响。您的公共方法有一个契约,它是如何实现的是一个实现细节。

您的方法将您的单元测试变成了一个(过于复杂的!)重新实现生产代码。这意味着:当你想要改变你的实现时,你的测试就需要进行调整。更糟糕的是,因为您将方法名作为原始字符串传递,所以直到运行时您才会注意到,这时方法突然停止返回whatever,而是给您dummy

所以,这里真正的答案是:

  • 首先,尽可能避免使用静态方法,这样您就不会对静态方法进行嘲弄
  • 忘记测试这样的实现细节。

考虑到OP的评论:

  • 静态比“状态”有更多的问题。它扼杀了多态性,还会导致对静态代码所在类的直接、硬依赖
  • 这不仅使单元测试变得更加困难,任何类型的测试也变得更加困难
  • 并且从我的个人经验来看:当人们告诉我“我需要PowerMock(ito)用于我新编写的代码”时,我就知道他们创建了难以测试的代码,而不需要这样做。完全有可能(也希望)以能够很好地通过较少侵入性的模拟框架进行测试的方式编写生产代码。

换句话说:如果您不能用Mockito编写简单的直接测试,那么很可能您创建了难以测试的生产代码,那么您最好投入时间和精力使生产代码更容易测试。而不是使用PowerMock(ito)锤子通过处理症状来“修复”您的问题。是的,这很重要。我们来自一个基于PowerMock的“太多静态”的代码库,并在某个时刻简单地告诉人们“不再”。从那以后,当我们需要嘲讽的时候,我们就用mockito。而在不同的地方由于“变更为静态”而导致的奇怪的“单元测试失败”的数量下降到了0。我们的生产代码变得更好了。

 类似资料:
  • 如何验证是否调用了私有嵌套类的非静态方法?这就是我目前的情况: 我明白了: 更新1: @丹尼斯,我试过以下方法,不过我得到了一个。我想根据JVM中已经存在的单例验证方法的运行,而不是创建它的新实例(正如我在下面的代码中所做的那样),以便调用方法。我尝试调用,但没有成功。有没有一种方法可以使用外部类的运行实例上的反射来验证jmockit中对私有嵌套类中非静态方法的调用(通过调用)? 更新2: 尝试获

  • 我目前在JUnit测试中遇到了障碍,需要一些帮助。所以我用静态方法得到了这个类,它将重构一些对象。为了简化起见,我举了一个小例子。这是我的工厂课程: 这是我的测试类: 基本上,我试图实现的是私有方法check String()应该被抑制(因此不会抛出异常),并且还需要验证方法check String()实际上是在方法factorObject()中调用的。 更新:抑制正常工作,代码如下: ... 但

  • 问题内容: 尝试在静态类中调用非静态方法时遇到错误。 无法从类型播放中静态引用非静态方法methodName() 我不能使该方法静态,因为这也给我一个错误。 此静态方法无法从xInterface隐藏实例方法 有什么办法可以在另一个静态方法中轮回调用非静态方法?(这两种方法位于单独的包和单独的类中)。 问题答案: 从静态方法中调用非静态方法的唯一方法是使类的实例包含非静态方法。根据定义,非静态方法是

  • 问题内容: 您如何看待使用 私有静态方法 ? 就个人而言,我更喜欢使用 静态 私有方法而不 是非 静态 方法,只要它不需要访问任何实例字段即可。 但是我听说这种做法违反了OOP原则。 编辑:我想从样式的角度来看,而不是性能。 问题答案: 一个方法本身本身并没有违反OOP,但是当类上有很多不需要(也不能*)访问实例字段的方法时,您就不会以OO方式进行编程,因为“对象”表示状态+一起定义的状态操作。如

  • Powermock为什么不模拟静态方法调用,而是在然后()语句中调用初始方法? 在这种情况下,我有一系列方法调用: TestClass方法-调用- Class4方法尝试查找上下文中不存在且挂起的对象,因此我尝试使用Powermock模拟公共静态Class3方法。 所有的类和方法都是非最终的。我使用TestNg。我的测试方法有一个@准备测试我尝试了以下方法来模拟方法调用: 或而不是当-然后返回: 或

  • 我试图验证在使用powerMockito 1.6.4测试服务方法时从未调用过静态方法 我按照这个答案做了同样的事情。 以下是我的代码。 我现在面临的问题是,调用real并给出nullPointerException。 我的假设是与一起工作,以便指定要验证的静态方法。 我错过什么了吗?