PowerMockito 在尝试存根私有重载方法时抛出 NullPointerException

2024-01-07

我(仍在)尝试检查是否bar(Alpha, Baz) called bar(Xray, Baz)使用 PowerMockito(如bar(Xray, Baz) is private) - 考虑到我的 MCVE 课程,实际上没有调用后者Foo以下。 (我上过同一堂课earlier https://stackoverflow.com/q/32206315/2018047,所有方法都在Foo being public- 万一你有似曾相识的感觉……)

public class Foo {
    private String bar(Xray xray, Baz baz) {
        return "Xray";
    }

    private String bar(Zulu zulu, Baz baz) {
        return "Zulu";
    }

    public String bar(Alpha alpha, Baz baz) {
        if(alpha.get() instanceof Xray) {
            return bar((Xray)alpha.get(), baz);
        } else if(alpha.get() instanceof Zulu) {
            return bar((Zulu)alpha.get(), baz);
        } else {
            return null;
        }
    }
}

当我尝试运行下面的测试时,我从 PowerMock 得到一个 NPE:

@RunWith(PowerMockRunner.class)
// @PrepareOnlyThisForTest(Foo.class) // we aren't looking at the byte code, I think
public class FooTest {

    @Test
    public void testBar_callsBarWithXray() throws Exception {
        Baz baz = new Baz(); //POJOs
        Alpha alpha = new Alpha();
        alpha.set(new Xray());

        Foo foo = new Foo();
        Foo stub = spy(foo); // using Mockito, as it's neither final nor "not spyable"

        // NPE at org.powermock.api.mockito.internal.expectation.PowerMockitoStubberImpl.addAnswersForStubbing(PowerMockitoStubberImpl.java:67)
        PowerMockito.doReturn("ok").when(stub, "bar", Xray.class, Baz.class);

        stub.bar(alpha, baz);
        // Testing if bar(Xray, Baz) was called by bar(Alpha, Baz)
        PowerMockito.verifyPrivate(foo).invoke("bar", Xray.class, Baz.class);
        // Mockito's equivalent for a public method: verify(stub, times(1)).bar(any(Xray.class), any(Baz.class));
    }
}

如果我将存根设为PowerMockito.spy(foo),我得到一个IllegalArgumentException: argument type mismatch at org.powermock.reflect.internal.WhiteboxImpl.performMethodInvocation(WhiteboxImpl.java:2014)反而。 (它与 NPE 在同一条线上冒泡。)

我正在使用 Mockito-core 1.9.5、PowerMock 1.5.4(module-junit4 和 api-mockito)和 JUnit 4.11。

我需要更改什么才能阻止抛出异常?我怎样才能让这个测试发挥作用? (以外testing that https://stackoverflow.com/a/32206838/2018047我的课有效,而不是how...;-))


在设置期望时,我们必须使用精确的参数匹配器。在你的情况下,它是 Matchers.any(Xray.class)、Matchers.any(Baz.class)

我已按如下方式修改了您的代码,并在测试方法的输出对象上添加了断言语句。

@RunWith(PowerMockRunner.class)
//@PrepareOnlyThisForTest(Foo.class) // we aren't looking at the byte code, I think
 public class FooTest {

   @Test
   public void testBar_callsBarWithXray() throws Exception {
       Baz baz = new Baz(); //POJOs
       Alpha alpha = new Alpha();
       alpha.set(new Xray());

       Foo foo = new Foo();
       Foo stub = PowerMockito.spy(foo); // using Mockito, as it's neither final nor "not spyable"

      // NPE at org.powermock.api.mockito.internal.expectation.PowerMockitoStubberImpl.addAnswersForStubbing(PowerMockitoStubberImpl.java:67)
      PowerMockito.doReturn("ok").when(stub, "bar", Matchers.any(Xray.class), Matchers.any(Baz.class));

      String res = stub.bar(alpha, baz);
      Assert.assertEquals("ok", res);

     //Testing if bar(Xray, Baz) was called by bar(Alpha, Baz)
     PowerMockito.verifyPrivate(stub).invoke("bar", Matchers.any(Xray.class), Matchers.any(Baz.class));
     // Mockito's equivalent for a public method: verify(stub, times(1)).bar(any(Xray.class), any(Baz.class));
   }
}

观察:当调用验证方法时,我们必须传递存根对象而不是实际对象,因为我们对存根对象设置了期望。由于我添加了断言语句来测试该方法,因此您不必在存根上验证它是否正常工作。

ADDED:我在公共和私有“bar”方法中添加了 sysout 语句,当我再次测试时,我发现公共 bar 方法的 sysout 语句没有打印。 这意味着上面的代码只模拟了公共方法,但没有模拟私有方法。

为了模拟私有“bar”方法,我尝试使用 MemberMatcher.method 进行另一种模拟,效果非常好。

import org.powermock.api.support.membermodification.MemberMatcher;

@RunWith(PowerMockRunner.class)
@PrepareForTest(Foo.class) // we need this
public class FooTest {

@Test
 public void testBar_callsBarWithXray() throws Exception {
     Baz baz = new Baz(); //POJOs
     Alpha alpha = new Alpha();
     alpha.set(new Xray());

     Foo stub = PowerMockito.spy(new Foo());

     PowerMockito.doReturn("ok")
        .when(stub,
                MemberMatcher.method(Foo.class,
                        "bar",
                        Xray.class, Baz.class))
        .withArguments(Matchers.any(Xray.class), Matchers.any(Baz.class));

     String res = stub.bar(alpha, baz);

     Assert.assertEquals("ok", res);

     //Testing if bar(Xray, Baz) was called by bar(Alpha, Baz)
     PowerMockito.verifyPrivate(stub).invoke("bar", Matchers.any(Xray.class), Matchers.any(Baz.class));
     // Mockito's equivalent for a public method: verify(stub, times(1)).bar(any(Xray.class), any(Baz.class));
 }

 output : public bar

测试方法也通过了。下面是具有 sysout 的 foo 方法。

private String bar(Xray xray, Baz baz) {
    System.out.println("private bar");
    return "Xray";
}

public String bar(Alpha alpha, Baz baz) {

    System.out.println("public bar");

    if(alpha.get() instanceof Xray) {
        return bar((Xray)alpha.get(), baz);
    } else if(alpha.get() instanceof Zulu) {
        return bar((Zulu)alpha.get(), baz);
    } else {
        return null;
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

PowerMockito 在尝试存根私有重载方法时抛出 NullPointerException 的相关文章

  • Java - 红、绿、蓝获取RGB

    通过致电getRGB int x int y with a BufferedImage对象 得到一个负数 如何将三个不同的值 红色 绿色和蓝色 转换为这个单个负数 使用颜色类 new Color r g b getRGB
  • 使用 Eclipse 将具有外部依赖项的 Java 项目导出到 jar

    有没有一种简单的方法可以将 Java 项目 包括其所有外部依赖项 导出到标准 jar 文件 我开发了一个使用多个 Apache 库的 SDK 我希望能够将该项目作为单个 jar 发布 到目前为止我找到的这个问题的答案要求将项目打包为 Run
  • Android CursorAdapter、ListView 和后台线程

    我一直在开发的这个应用程序有包含数兆字节数据的数据库可供筛选 许多活动只是列表视图 通过数据库中的各个级别的数据下降 直到到达 文档 即从数据库中提取并显示在手机上的 HTML 我遇到的问题是 其中一些活动需要能够通过捕获击键并重新运行带有
  • 探索java图像处理的好资源[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我是图像处理领域的新手 请推荐一些好的资源 书籍和网络链接 来学习 Java 中的图像处理 最适合隐写术分析 适合初学者和高级水平 我看过
  • Java - toString 到 Color

    我一整天都在努力解决这个问题 基本上我做了一个 for 循环 将条目添加到数组列表中 其中一项是 颜色 变量 我已经用过random nextInt为颜色构造函数的红色 绿色和蓝色部分创建新值 我还设置了一个toString方法 这样我就可
  • 在 Java 中的 JFrame/JPanel/JComponent 中添加 Web 浏览器

    我正在开发一个 Java 应用程序 需要在应用程序中使用 Web 浏览器 我见过一些应用程序这样做 例如在同一应用程序中单击左侧面板中的提要并打开右侧面板中的链接时的 RSS 阅读器 我想实现类似的功能 在java中可以做到这一点吗 Jav
  • 使用java在网页中进行字符编码

    如何使用java找出网页中的字符编码类型 打开与 URL 的连接 使用URL openConnection http download oracle com javase 6 docs api java net URL html openC
  • 开发人员实际上是否使用 vim 在 Windows 操作系统上编写代码(Java)? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • EJB 中 @Stateless 相对于 @Singleton 的真正用例是什么

    如果我正确理解EJB Singleton实际上与普通Java中的Singleton相同 也是spring中的单例 gt 一个实例 每个调用同时通过同一个实例 Stateless 声明一个 bean 它可以 但不得 具有多个实例 但限制是一个
  • 单元测试、集成测试还是设计中的问题?

    我编写了我的第一个单元测试 我认为它过于依赖其他模块 我不确定是否是因为 这是一个复杂的测试 我实际上已经编写了集成测试或 我的设计有问题 我首先要说的是 虽然我有大约 4 年的开发经验 但我从未学过 也没有人教过自动化测试 我刚刚使用 H
  • 如何从 Trie 中检索给定长度的随机单词

    我有一个简单的 Trie 用来存储大约 80k 长度为 2 15 的单词 它非常适合检查字符串是否是单词 但是 现在我需要一种获取给定长度的随机单词的方法 换句话说 我需要 getRandomWord 5 来返回 5 个字母的单词 所有 5
  • Java 常量枚举[重复]

    这个问题在这里已经有答案了 可能的重复 理解 Java 中的枚举 https stackoverflow com questions 1419835 understanding enums in java 为什么我们应该使用枚举而不是 Ja
  • Java 中通用方法参数的 getClass()

    以下 Java 方法无法编译
  • 如何加载图像文件到ImageView?

    我试图在从文件选择器中选择图像文件后立即显示该图像文件 文件选择器仅限于 png 和 jpg 文件 所选文件存储在文件类型的变量中 为此 我设置了一个 ImageView 我希望用这个新文件设置图像 唯一的问题是它的类型是文件而不是图像 如
  • SDK尚未初始化,请务必先调用FacebookSdk.sdkInitialize()

    我在实现 Facebook SDK 时遇到此错误 并且我tried https stackoverflow com questions 15490399 error inflating class com facebook widget l
  • 测量 tomcat 的排队请求数

    因此 使用tomcat 您可以设置acceptCount值 默认为100 这意味着当所有工作线程都忙时 新连接被放置在队列中 直到队列满 之后它们被拒绝 我想要的是监视此队列中项目的大小 但无法确定是否有办法通过 JMX 获取此值 即不是队
  • 使用 Commons 或 Guava 将文本文件转换为 Java Set

    我想将文件中的每一行加载到 HashSet 集合中 有没有一种简单的方法可以做到这一点 怎么样 Sets newHashSet Files readLines file charSet 使用番石榴 参考 文件 readLines http
  • 在java中创建一个XML树并将其转换为json对象

    我尝试创建也能够转换为 json 的树 但对于只有一个xpath 当我尝试实现多个 xpath 时 我无法获得所需的输出 这里我分享一下我的实现 private static Document addElemtbypath List
  • 接口中“不能降低继承方法的可见性”的含义

    我有两个文件 public interface PrintService void print PrintDetails details class PrintDetails private String printTemplate pub
  • AES 密钥是随机的吗?

    AES 密钥可以通过此代码生成 KeyGenerator kgen KeyGenerator getInstance AES kgen init 128 but 如果我有一个 非常可靠 的生成随机数的方法 我可以这样使用它吗 SecureR

随机推荐