为java http客户端编写Mock类

时间:2016-11-08 21:00:54

标签: java unit-testing mockito

我正在尝试为我的HTTP客户端编写单元测试用例,并希望使用mockito来模拟从服务器收到的响应。

public HttpResponse postRequest(String uri, String body) throws IOException {
        HttpResponse response;
        String url = baseUrl + uri;
        try (CloseableHttpClient httpClient = HttpClientBuilder.create()
                .build()) {
            HttpPost post = new HttpPost(url);
            post.setEntity(new StringEntity(body));
            post.setHeader(AUTHORIZATION_HEADER, authorization);
            post.setHeader(CONTENTTYPE_HEADER, APPLICATION_JSON);
            post.setHeader(ACCEPT_HEADER, APPLICATION_JSON);

            response = httpClient.execute(post);
        } catch (IOException e) {
            System.out.println("Caught an exception" + e.getMessage().toString());
            logger.error("Caught an exception" + e.getMessage().toString());
            throw e;
        }
        return response;
    }

我的测试课如下。我无法弄清楚应该如何发送我的回复正文。

public class HTTPRequestTest extends Mockito {
    private String body = "{a:b}";

    @Test
    public void xyz throws Exception {
        HttpClient httpClient = mock(HttpClient.class);
        HttpPost httpPost = mock(HttpPost.class);
        HttpResponse httpResponse = mock(HttpResponse.class);
        StatusLine statusLine = mock(StatusLine.class);

        when(httpClient.execute(httpPost)).thenReturn(body);
    }
}

3 个答案:

答案 0 :(得分:4)

使用PowerMockito: 首先注释您的测试类

@RunWith(PowerMockRunner.class)

@PrepareForTest(HttpClientBuilder.class)

然后您的测试方法可能类似于:

  @Test
public void xyz() throws Exception {
    HttpClientBuilder mockClientBuilder = PowerMockito.mock(HttpClientBuilder.class);
    CloseableHttpClient mockHttpClient = PowerMockito.mock(CloseableHttpClient.class);
    CloseableHttpResponse mockResponse = PowerMockito.mock(CloseableHttpResponse.class);
    PowerMockito.mockStatic(HttpClientBuilder.class);

    PowerMockito.when(HttpClientBuilder.class, "create").thenReturn(mockClientBuilder);
    PowerMockito.when(mockClientBuilder.build()).thenReturn(mockHttpClient);
    PowerMockito.when(mockHttpClient.execute(any(HttpPost.class))).thenReturn(mockResponse);

    HttpResponse response = classUnderTest.postRequest("uri", "body");
    //assertResponse 
}

答案 1 :(得分:0)

问题是您的HttpClient模拟未在单元测试中使用。

您的postRequest函数使用此方法创建一个新的HttpClient:

HttpClientBuilder.create().build()

HttpClientBuilder实例化一个新的HttpClient,它是一个完全独立的HttpClient实例,而不是你在单元测试中创建的模拟。不幸的是,没有一种简单的方法来测试您编写的代码,因为Mockito无法模拟静态方法(如HttpClientBuilder.create)。有关此问题的更多讨论以及可能的解决方法,请参阅this post

总结一下这篇文章,您可以选择重写代码,以便更轻松地注入模拟,或者切换到可以模拟静态方法的模拟框架(如PowerMock)。

答案 2 :(得分:0)

如其他答案中所建议,PowerMock绝对是模拟静态方法的一个选项(在您的情况下为HttpClientBuilder.create()。build()),但是,对于您的特定实例,您还可以通过移动从doPost方法实例化HttpClient并将其声明为实例变量。

@Mock
CloseableHttpClient httpClient = HttpClientBuilder.create().build()

这样,当您使用Mockito进行模拟时,它将是一个模拟对象。在JUnit5中,可以通过在CloseableHttpClient声明上方使用@Mock,然后在setup方法中初始化所有模拟来完成。