【问题标题】:How to Mock HttpClientBuilder for Unit Tests如何模拟 HttpClientBuilder 进行单元测试
【发布时间】:2019-09-18 09:16:12
【问题描述】:

我正在尝试为 http post 实现编写单元测试。但是我无法正确模拟 httpclient,并且我的 when 语句永远不会被触发。我编写的单元测试是进行实际的 http 调用,而不是使用模拟响应进行响应。 我们如何继续模拟由 HttpClientBuilder 创建的客户端?

Http方法实现:

HttpResponse postRequest(String url, String request) {
    HttpResponse resp = null;
    try {
        HttpClient client = HttpClientBuilder.create().useSystemProperties().build();
        HttpPost post = new HttpPost(url);
        post.addHeader("Content-Type", "application/x-www-form-urlencoded");
        post.setEntity(new StringEntity(request));

        resp = client.execute(post);
    } catch (Exception e) {
        return null;
    }
}

测试方法:

@Mock
private HttpClient httpClient;

when(httpClient.execute(any())).thenReturn(httpResponse);

【问题讨论】:

  • 你能把postRequest所在的整个班级和完整的测试班一起发布吗?

标签: java unit-testing http mockito


【解决方案1】:

我们如何继续模拟由 HttpClientBuilder 创建的客户端?

我们没有!!!

尽量避免嘲笑第三者的担忧

创建紧密耦合的静态实现关注点的抽象

public interface HttpClientFactory {
    public HttpClient create();
}

具有将用于生产的简单实现。

public class HttpClientFactoryImpl implements HttpClientFactory {

    //...

    public HttpClient create() {
        return HttpClientBuilder.create().useSystemProperties().build();
    }

    //...
}

使用依赖倒置,封装类应该显式依赖抽象以避免违反单一职责原则(SRP)

public class SystemUnderTest {

    private HttpClientFactory httpClientFactory;

    public SystemUnderTest(HttpClientFactory httpClientFactory) {
        this.httpClientFactory = httpClientFactory;
    }

    HttpResponse postRequest(String url, String request) {
        HttpResponse resp = null;
        try {
            HttpClient client = httpClientFactory.create();
            HttpPost post = new HttpPost(url);
            post.addHeader("Content-Type", "application/x-www-form-urlencoded");
            post.setEntity(new StringEntity(request));

            resp = client.execute(post);
            return resp;
        } catch (Exception e) {
            return null;
        }
    }
}

这种关注点分离 (SoC) 允许它(您的封装类)更灵活地进行单独的单元测试。

@Test
public void testPostRequest() throws Exception {
    // Arrange
    HttpResponse expected = mock(HttpResponse.class);
    HttpClient httpClient = mock(HttpClient.class);
    when(httpClient.execute(any())).thenReturn(expected);

    HttpClientFactory httpClientFactory = mock(HttpClientFactory.class);
    when(httpClientFactory.create()).thenReturn(httpClient);

    SystemUnderTest systemUnderTest = new SystemUnderTest(httpClientFactory);

    String url = "http://url_here";
    String request = "Hello World";

    // Act
    HttpResponse actual = systemUnderTest.postRequest(url, request);

    // Assert
    assertEquals(expected, actual);
    //should also verify that the expected arguments as passed to execute()
}

【讨论】:

    猜你喜欢
    • 2018-04-04
    • 2021-09-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多