使用 WireMock 进行更全面的 API 调用测试

1,348 阅读2分钟

之前写了一篇介绍 HttpClient 的两种重试机制 的文章, 但是否真的会按照预期进行重试我们不得而知。

别人提供给我们的 API 往往都是正常的,很多错误并不能稳定重现,这也造成了我们无法进行全面的测试。正是这种情况下,了解到了 WireMock。

本文不打算做一个入门教程,重点在于如何用 WireMock 解决实际的问题。WireMock 官网的文档很不错,想要深入了解的可以去阅读一下。

初始化调用端

首先初始化一个HttpClient

public ZwroksApi(){
    RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(1000).build();
    DefaultServiceUnavailableRetryStrategy serviceUnavailableRetryStrategy = new DefaultServiceUnavailableRetryStrategy();
    httpClient = HttpClients.custom()
        .setServiceUnavailableRetryStrategy(serviceUnavailableRetryStrategy)
        .setDefaultRequestConfig(requestConfig)
        .build();
}

进行了如下配置

  1. 异常重试默认开启,重试3次。
  2. 使用了默认的服务不可用重试策略,会重试1次,间隔1秒。
  3. 设置 SocketTimeout 为1秒,用于模拟超时。

异常重试

超时

首先来模拟一下超时,设置了固定的 delay 2秒,所以一定会超时,按照预期会重试3次,所以一共是请求4次。

@Test
public void testSocketTimeOut() {
    stubFor(get(urlEqualTo("/test"))
            .willReturn(aResponse()
                        .withStatus(HttpStatus.SC_OK)
                        .withHeader("Content-Type", "text/xml")
                        .withBody("ok")
                        .withFixedDelay(2000)));
    zwroksApi.test();
    verify(4, getRequestedFor(urlEqualTo("/test")));
}

但是结果呢

Expected exactly 4 requests matching the following pattern but received 1

具体的原因在之前那篇文章也已经提过,SocketTimeoutExceptionInterruptedIOException 的子类,不会重试。

如何超时也进行重试,在上一篇中也有讲,这里就不赘述了。

错误返回

WireMock 中提供了几种错误返回,使用也很简单

@Test
public void testBadResponse() {
    stubFor(get(urlEqualTo("/test"))
            .willReturn(aResponse().withFault(Fault.CONNECTION_RESET_BY_PEER)));
    zwroksApi.test();
    verify(4, getRequestedFor(urlEqualTo("/test")));
}

这里在运行时会抛错 java.net.SocketException: Connection reset,这种异常是会进行重试的,所以这里测试可以通过。

服务不可用重试

调用的代码如下,我希望在返回503的时候进行重试

@Test
public void testServiceUnavailable() {
    stubFor(get(urlEqualTo("/test"))
            .willReturn(aResponse()
                        .withStatus(HttpStatus.SC_SERVICE_UNAVAILABLE)
                        .withHeader("Content-Type", "text/xml")
                        .withBody("service unavailable")));
    zwroksApi.test();
    verify(2, getRequestedFor(urlEqualTo("/test")));
}

这里测试也是可以通过的。WireMock 提供了获取请求日志的能力,除了次数,我们可以看看是否两次请求是间隔了一秒。

    List<ServeEvent> allServeEvents = getAllServeEvents();
    long firstTime = allServeEvents.get(1).getRequest().getLoggedDate().getTime();
    long lastTime = allServeEvents.get(0).getRequest().getLoggedDate().getTime();
    assert lastTime - firstTime > 1000;