Powermockito私有方法模拟NullPointerException。调用私有方法。

5
我可以帮您翻译为中文。以下是翻译内容:

我正在尝试模拟一个私有方法(executeGetRequest),在声明我要返回给私有方法的模拟的那一行中,实际上使用了空参数执行了私有方法,因此引发了NullPointerException。

VlcPlayerMinimal.java:

package com.nicobrest.kamehouse.vlcrc.model;

public class VlcPlayerMinimal {

  public static void main(String[] args) {
    String vlcRcStatus = new VlcPlayerMinimal().getVlcRcStatus();
    System.out.println(vlcRcStatus);
  }

  public String getVlcRcStatus() {
    Client client = new Client();
    GetRequest getRequest = new GetRequest();
    String vlcRcStatus = executeGetRequest(client, getRequest);
    return vlcRcStatus;
  }

  private String executeGetRequest(Client client, GetRequest getRequest) {
    return client.execute(getRequest);
  }

  private class Client {
    public String execute(GetRequest getRequest) {
      return "{status: playing, id: 1}";
    }
  }
  private class GetRequest { 
  }
}

VlcPlayerMinimalTest.java:

package com.nicobrest.kamehouse.model;

import static org.junit.Assert.*;
import static org.mockito.ArgumentMatchers.any;

import com.nicobrest.kamehouse.vlcrc.model.VlcPlayerMinimal;

import org.junit.Test;
import org.powermock.api.mockito.PowerMockito;

public class VlcPlayerMinimalTest {

  @Test
  public void getVlcRcStatusTest() {
    VlcPlayerMinimal vlcPlayerSpy = PowerMockito.spy(new VlcPlayerMinimal());
    try {
      PowerMockito.doReturn("{status: stopped, id: 2}").when(vlcPlayerSpy, "executeGetRequest", any(), any());
      String vlcRcStatus = vlcPlayerSpy.getVlcRcStatus();
      System.out.println(vlcRcStatus);
    } catch (Exception e) {
      e.printStackTrace();
      fail("Unexpected exception thrown.");
    }
  }
}

堆栈跟踪:

java.lang.NullPointerException
    at com.nicobrest.kamehouse.vlcrc.model.VlcPlayerMinimal.executeGetRequest(VlcPlayerMinimal.java:18)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.powermock.reflect.internal.WhiteboxImpl.performMethodInvocation(WhiteboxImpl.java:1846)
    at org.powermock.reflect.internal.WhiteboxImpl.doInvokeMethod(WhiteboxImpl.java:810)
    at org.powermock.reflect.internal.WhiteboxImpl.invokeMethod(WhiteboxImpl.java:675)
    at org.powermock.reflect.Whitebox.invokeMethod(Whitebox.java:401)
    at org.powermock.api.mockito.internal.expectation.PowerMockitoStubberImpl.when(PowerMockitoStubberImpl.java:95)
    at com.nicobrest.kamehouse.model.VlcPlayerMinimalTest.getVlcRcStatusTest(VlcPlayerMinimalTest.java:17)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
...

看起来PowerMockito实际上是在调用我试图模拟的方法,即在这一行中:PowerMockito.doReturn("{status: stopped, id: 2}").when(vlcPlayerSpy, "executeGetRequest", any(), any());

由于客户端为null,它正在调用execute(getClient)方法,但那是我试图在测试中避免调用的方法。

有什么想法可以解决这个问题吗?我已经尝试了一段时间,但没有成功。

我使用的是Java 8、powermock 1.7.3和junit 4.12。


你想要测试什么? - mickaelw
我想在VlcPlayer类中测试getVlcRcStatus方法,该方法调用VLC Web API,然后生成自定义状态对象。(如果需要,我可以发布整个代码)。一旦它能够正常工作,我将在调用vlcPlayerSpy.getVlcRcStatus()之后为测试用例添加验证。我将调用VLC的Web API包装在私有方法executeGetRequest中,以模拟API调用并测试我的其余代码。 - nbrest
2
你能发布一个 [mcve] 吗? - user180100
谢谢RC。我用一个最小、完整和可验证的示例替换了之前放置的示例代码,该示例只使用了一个类及其测试用例,以复制相同的问题。 - nbrest
2
我认为问题在于测试类上缺少@PrepareForTest(xxx) - user180100
谢谢RC!那就是问题所在。我还必须添加@RunWith(PowerMockRunner.class)。在我的实际情况中,当尝试模拟apache HttpResponse.class和HttpEntity.class时,我现在遇到了麻烦,但是您的评论解决了问题。非常感谢! - nbrest
1个回答

4

这个测试成功了:

package foo.bar;

import static org.junit.Assert.*;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

@RunWith(PowerMockRunner.class)
@PrepareForTest(VlcPlayerMinimal.class)
public class VlcPlayerMinimalTest {

  @Test
  public void getVlcRcStatusTest() {
    VlcPlayerMinimal vlcPlayerSpy = PowerMockito.spy(new VlcPlayerMinimal());
    try {
      PowerMockito.doReturn("{status: stopped, id: 2}").when(vlcPlayerSpy, "executeGetRequest", Mockito.any(), Mockito.any());
      String vlcRcStatus = vlcPlayerSpy.getVlcRcStatus();
      System.out.println(vlcRcStatus);
    } catch (Exception e) {
      e.printStackTrace();
      fail("Unexpected exception thrown.");
    }
  }
}

你需要这些类级注释:

@RunWith(PowerMockRunner.class)
@PrepareForTest(VlcPlayerMinimal.class)

控制台输出:

{状态:已停止,ID:2}

输入图像描述


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接