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

他人提供给咱们的 API 往往都是失常的,很多谬误并不能稳固重现,这也造成了咱们无奈进行全面的测试。正是这种状况下,理解到了 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次。

@Testpublic 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 中提供了几种谬误返回,应用也很简略

@Testpublic 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的时候进行重试

@Testpublic 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;

这里只是介绍了一小部分 WireMock 的性能,更多的性能能够去官网看文档,十分好懂。