【问题标题】:NullPointerException at mocked class method模拟类方法中的 NullPointerException
【发布时间】:2017-06-07 10:14:11
【问题描述】:

我目前正在为 Buy 类的方法 buy 编写一个测试,它实际上应该测试正确的请求是否发送到服务器以及它是否正确处理了响应。

目前我总是收到 java.lang.NullPointerException,因为 execute(post) 返回 null 而不是 CloseableHttpResponse。

CloseableHttpResponse 响应 = httpClient.execute(post);

但我不明白,因为在我的测试中我告诉 mockito 返回模拟后的 closeableHttpResponse。

测试

  @Test
    public void testBid() throws IOException {
        //given:
        HttpPost post = mock(HttpPost.class);
        HttpResponse httpResponse = mock(HttpResponse.class);

        StatusLine statusLine = mock(StatusLine.class);

        ObserverImp observer = mock(ObserverImp.class);

        CloseableHttpClient closeableHttpClient = mock(CloseableHttpClient.class);
        CloseableHttpResponse closeableHttpResponse = mock(CloseableHttpResponse.class);
        HttpEntity httpEntity = mock(HttpEntity.class);
        BufferedInputStream inputStream = mock(BufferedInputStream.class);

        //and:
        when(statusLine.getStatusCode()).thenReturn(200);
        when(httpResponse.getStatusLine()).thenReturn(statusLine);
        when(closeableHttpClient.execute(post)).thenReturn(closeableHttpResponse);
        when(closeableHttpResponse.getEntity()).thenReturn(httpEntity);
        when(httpEntity.getContent()).thenReturn(inputStream);
        when(inputStream.read()).thenReturn(1);
        when(observer.getKey()).thenReturn("##213");


        Buy buy = new Buy(observer, closeableHttpClient);
        buy.bid(14455);
    }

以及相关的实现

public class Buy {
    private ObserverImp observer;
    private CloseableHttpClient httpClient;

    public Buy (ObserverImp observer, CloseableHttpClient httpClient) {
       this.observer = observer;
       this.httpClient = httpClient;
    }

    public void buy(double price) {
            String queryArgs = "command=order&amount=1" + "&price=" + String.valueOf(price); // generates query

            HttpPost post = new HttpPost("wwww.hm.edu/projectGroup1");
            post.addHeader("Key", observer.getKey());
            try {
                post.setEntity(new ByteArrayEntity(queryArgs.getBytes("UTF-8")));
            } catch (UnsupportedEncodingException e) {
                System.out.println("Exception in run");
            }
            List<NameValuePair> params = new ArrayList<>();

            params.add(new BasicNameValuePair("command", "order"));
            params.add(new BasicNameValuePair("amount", "1"));
            params.add(new BasicNameValuePair("price", String.valueOf(price)));
            try {
                post.setEntity(new UrlEncodedFormEntity(params));
                CloseableHttpResponse response = httpClient.execute(post);
                HttpEntity entity = response.getEntity();
                Scanner in = new Scanner(entity.getContent());
                String orderNumber = "";
                while (in.hasNext()) {
                    orderNumber = in.nextLine();
                }
                String[] findOrderNumber = orderNumber.split(".");
                long lastOrderNumber = -1;
                try {
                    lastOrderNumber = Long.valueOf(findOrderNumber[3]);
                } catch (NumberFormatException exception) {
                    System.out.println("NumberFormatException");
                } finally {
                    if (lastOrderNumber != -1) {
                        observer.setOrderNumber(lastOrderNumber);
                    }
                }
                in.close();
                EntityUtils.consume(entity);
                httpClient.close();
            } catch (IOException e) {
                System.out.println("Exception occured during process");
            }
        }
}

请帮我解决这个问题。非常感谢。

【问题讨论】:

  • Mocks 默认返回null。如果您期望其他任何东西,您应该正确设置它们。
  • 你的测试代码有很多问题。首先声明 HttpClients.createDefault 不能使用 mockito 来模拟。你需要 powermock 才能这样做
  • 是的,你还没有嘲笑这一行CloseableHttpClient httpClient = HttpClients.createDefault();
  • 抱歉,我的剪贴板中的课程版本错误。我修好了它。我还需要用上面的代码对 HttpClients 的 createDefault 方法进行 powermock 吗?

标签: java testing mockito


【解决方案1】:

你需要那个:

when(closeableHttpClient.execute(any(HttpPost.class))).thenReturn(closeableHttpResponse);

您的代码之前只是等待您在测试中创建的确切帖子(等于)。但是您的购买方法会产生另一个帖子。这就是为什么您的 execute(post) 无法匹配班级的原因。 any() 解决了这个问题

【讨论】:

  • 成功了!谢谢你的解释。这是有道理的:)
【解决方案2】:

需要设置返回类型,默认情况下mock会返回null。同样在实现中调用 createDefault http 对象。

【讨论】:

  • 感谢您的回答。我以为这是返回具体类型?:when(closeableHttpClient.execute(post)).thenReturn(closeableHttpResponse);
  • 不,您正在检查closeableHttpClient 是否获得特定的post 对象(您的模拟对象),但实际上,它会得到这个:HttpPost post = new HttpPost("wwww.hm.edu/projectGroup1");
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-10
  • 1970-01-01
  • 2018-05-03
  • 1970-01-01
  • 2019-07-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多