如何测试SpringWebClient什么时候重试?
How to test Spring WebClient retry when?
我需要实现以下行为:
- 发出 REST post 请求
- 如果响应 returns 状态为
429 Too many requests
,最多重试 3 次,延迟 1 秒
- 如果第三次重试失败或发生任何其他错误,记录并写入数据库
- 如果请求成功(http 状态 200),记录一些信息
我想为此目的使用 Spring WebClient 并想出了这个代码:
Mono<ClientResponse> response = webClient.post()
.uri(URI.create("/myuri"))
.body(BodyInserters.fromObject(request))
.retrieve()
.onStatus(httpStatus -> httpStatus.equals(HttpStatus.TOO_MANY_REQUESTS),
response -> Mono.error(new TooManyRequestsException("System is overloaded")))
.bodyToMono(ClientResponse.class)
.retryWhen(Retry.anyOf(TooManyRequestsException.class)
.fixedBackoff(Duration.ofSeconds(1)).retryMax(3))
.doOnError(throwable -> saveToDB(some_id, throwable))
.subscribe(response -> logResponse(some_id, response));
现在我想测试重试机制和错误处理是否如我所料。可能我可以使用 StepVerifier 来达到这个目的,但我只是不知道如何在我的案例中使用它。有什么有用的提示吗?
我认为您可以使用模拟网络服务器对此进行测试,例如MockWebServer.
@Test
public void testReactiveWebClient() throws IOException
{
MockWebServer mockWebServer = new MockWebServer();
String expectedResponse = "expect that it works";
mockWebServer.enqueue(new MockResponse().setResponseCode(429));
mockWebServer.enqueue(new MockResponse().setResponseCode(429));
mockWebServer.enqueue(new MockResponse().setResponseCode(429));
mockWebServer.enqueue(new MockResponse().setResponseCode(200)
.setBody(expectedResponse));
mockWebServer.start();
HttpUrl url = mockWebServer.url("/mvuri");
WebClient webClient = WebClient.create();
Mono<String> responseMono = webClient.post()
.uri(url.uri())
.body(BodyInserters.fromObject("myRequest"))
.retrieve()
.onStatus(
httpStatus -> httpStatus.equals(HttpStatus.TOO_MANY_REQUESTS),
response -> Mono.error(new TestStuff.TooManyRequestsException("System is overloaded")))
.bodyToMono(String.class)
.retryWhen(Retry.anyOf(TestStuff.TooManyRequestsException.class)
.fixedBackoff(Duration.ofSeconds(1)).retryMax(3));
StepVerifier.create(responseMono)
.expectNext(expectedResponse)
.expectComplete().verify();
mockWebServer.shutdown();
}
如果您使用状态码 429
入队另一个 MockResponse
,验证将失败,例如错误代码 500
.
Dominik Sandjaja 的回答基本上帮助我设置了测试。为了完整起见,我 post 这里是工作版本:
@Test
public void mytest() {
MockResponse mockResponse = new MockResponse()
.setHeader(HttpHeaders.CONTENT_TYPE, "application/json")
.setResponseCode(429).setBody("Too many requests");
mockWebServer.enqueue(mockResponse);
mockWebServer.enqueue(mockResponse);
mockWebServer.enqueue(mockResponse);
mockWebServer.enqueue(mockResponse);
Mono<MyClass> responseMono = methodDoingTheAsyncCall.sendAsync(...);
StepVerifier.create(responseMono)
.expectError(RetryExhaustedException.class)
.verify();
}
我需要实现以下行为:
- 发出 REST post 请求
- 如果响应 returns 状态为
429 Too many requests
,最多重试 3 次,延迟 1 秒 - 如果第三次重试失败或发生任何其他错误,记录并写入数据库
- 如果请求成功(http 状态 200),记录一些信息
我想为此目的使用 Spring WebClient 并想出了这个代码:
Mono<ClientResponse> response = webClient.post()
.uri(URI.create("/myuri"))
.body(BodyInserters.fromObject(request))
.retrieve()
.onStatus(httpStatus -> httpStatus.equals(HttpStatus.TOO_MANY_REQUESTS),
response -> Mono.error(new TooManyRequestsException("System is overloaded")))
.bodyToMono(ClientResponse.class)
.retryWhen(Retry.anyOf(TooManyRequestsException.class)
.fixedBackoff(Duration.ofSeconds(1)).retryMax(3))
.doOnError(throwable -> saveToDB(some_id, throwable))
.subscribe(response -> logResponse(some_id, response));
现在我想测试重试机制和错误处理是否如我所料。可能我可以使用 StepVerifier 来达到这个目的,但我只是不知道如何在我的案例中使用它。有什么有用的提示吗?
我认为您可以使用模拟网络服务器对此进行测试,例如MockWebServer.
@Test
public void testReactiveWebClient() throws IOException
{
MockWebServer mockWebServer = new MockWebServer();
String expectedResponse = "expect that it works";
mockWebServer.enqueue(new MockResponse().setResponseCode(429));
mockWebServer.enqueue(new MockResponse().setResponseCode(429));
mockWebServer.enqueue(new MockResponse().setResponseCode(429));
mockWebServer.enqueue(new MockResponse().setResponseCode(200)
.setBody(expectedResponse));
mockWebServer.start();
HttpUrl url = mockWebServer.url("/mvuri");
WebClient webClient = WebClient.create();
Mono<String> responseMono = webClient.post()
.uri(url.uri())
.body(BodyInserters.fromObject("myRequest"))
.retrieve()
.onStatus(
httpStatus -> httpStatus.equals(HttpStatus.TOO_MANY_REQUESTS),
response -> Mono.error(new TestStuff.TooManyRequestsException("System is overloaded")))
.bodyToMono(String.class)
.retryWhen(Retry.anyOf(TestStuff.TooManyRequestsException.class)
.fixedBackoff(Duration.ofSeconds(1)).retryMax(3));
StepVerifier.create(responseMono)
.expectNext(expectedResponse)
.expectComplete().verify();
mockWebServer.shutdown();
}
如果您使用状态码 429
入队另一个 MockResponse
,验证将失败,例如错误代码 500
.
Dominik Sandjaja 的回答基本上帮助我设置了测试。为了完整起见,我 post 这里是工作版本:
@Test
public void mytest() {
MockResponse mockResponse = new MockResponse()
.setHeader(HttpHeaders.CONTENT_TYPE, "application/json")
.setResponseCode(429).setBody("Too many requests");
mockWebServer.enqueue(mockResponse);
mockWebServer.enqueue(mockResponse);
mockWebServer.enqueue(mockResponse);
mockWebServer.enqueue(mockResponse);
Mono<MyClass> responseMono = methodDoingTheAsyncCall.sendAsync(...);
StepVerifier.create(responseMono)
.expectError(RetryExhaustedException.class)
.verify();
}