如何模拟HttpClient类以返回不同的响应

时间:2019-04-04 00:40:50

标签: java mockito powermockito

如何使Mockito返回不同的HttpEntity值以响应不同的URI?

该测试将使用mockHttpClient发出多个HTTP请求(它们都是POST请求)。

HttpEntity httpEntity = EntityBuilder.create().setText(response).build();
PowerMockito.when(response, "getEntity").thenReturn(httpEntity);

测试本身就是这样设计的:

CloseableHttpClient client = mockHttpClient(200, HTTP_ENTITY);
runTest();
Mockito.verify(client, Mockito.times(2)).execute(Mockito.any());

对于上面的测试,它返回不同的HTTP实体,我尝试了以下操作:

CloseableHttpClient client = Mockito.mock(CloseableHttpClient.class);
    Mockito.when(client.execute(new HttpPost("http://127.0.0.1:8000/new/a"))).thenReturn(resp1);
    Mockito.when(client.execute(new HttpPost("http://127.0.0.1:8000/new/a/b"))).thenReturn(resp2);

但是我无法建立不同的http实体,并且无法基于请求中的URI做出响应。

2 个答案:

答案 0 :(得分:2)

首先,在这种情况下不需要Powermock。您不需要模拟静态方法,构造函数或其他讨厌的东西。

我已经准备了一个小示例测试,该测试对我来说Mockito 2.23.4开箱即用,您可以看到断言 isSameAs (“验证实际值是否与给定值相同,即使用==比较。”)确实检查某个POST调用是否与先前模拟的响应匹配:

public class CloseableHttpClientTest {
    private final CloseableHttpClient client = mock(CloseableHttpClient.class);

    @Test
    public void mockClient() throws IOException {
        // given
        CloseableHttpResponse resp1 = mock(CloseableHttpResponse.class);
        CloseableHttpResponse resp2 = mock(CloseableHttpResponse.class);
        HttpPost post1 = new HttpPost("http://127.0.0.1:8000/new/a");
        HttpPost post2 = new HttpPost("http://127.0.0.1:8000/new/a/b");
        when(client.execute(post1)).thenReturn(resp1);
        when(client.execute(post2)).thenReturn(resp2);

        // when
        CloseableHttpResponse returnedResp1 = client.execute(post1);
        CloseableHttpResponse returnedResp2 = client.execute(post2);

        // then
        assertThat(returnedResp1).isSameAs(resp1);
        assertThat(returnedResp2).isSameAs(resp2);
        verify(client).execute(post1);
        verify(client).execute(post2);
    }
}

答案 1 :(得分:0)

谢谢。 您的回复帮助我了解了如何更好地构建测试。但是在这种情况下,我试图在不进行任何重组的情况下修改它。

我以为我会在这里发布答案,以防万一有人在寻找答案。

Mockito.doAnswer(new Answer<CloseableHttpResponse>() {
  @Override
  public CloseableHttpResponse answer(InvocationOnMock invocation) {
    CloseableHttpResponse httpResponse = Mockito.mock(CloseableHttpResponse.class);

    // No change to status code based on endpoints
    Mockito.when(status.getStatusCode()).thenReturn(withResponseCode);
    Mockito.when(httpResponse.getStatusLine()).thenReturn(status);

    HttpEntity entity = Mockito.mock(HttpEntity.class);
    Object[] args = invocation.getArguments();
    String endpoint = ((HttpPost) args[0]).getURI().getPath();
    if (endpoint.contains("/a/b")) {
      entity = EntityBuilder.create().setText("something").build();
      Mockito.when(httpResponse.getEntity()).thenReturn(entity);
    } else {
      entity = EntityBuilder.create().setText("something else").build();
      Mockito.when(httpResponse.getEntity()).thenReturn(entity);
    }
    return httpResponse;
  }
}).when(client).execute(Mockito.any(HttpUriRequest.class)); 

集成测试不会测试其余客户端本身,并且我不需要旋钮和多个模拟客户端来获得不同的响应。以上帮助我根据接收请求的端点返回不同的响应。