rx-java - 如何测试 Spring WebClient 何时重试?

标签 rx-java reactive-programming project-reactor spring-webclient

我需要实现以下行为:

  • 发出 REST 发布请求
  • 如果响应返回状态 429 Too many requests , 最多重试 3 次,延迟 1 秒
  • 如果第三次重试失败或发生任何其他错误,请记录并写入数据库
  • 如果请求成功(http status 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为此目的,但我无法弄清楚如何在我的情况下使用它。有什么有用的提示吗?

    最佳答案

    我认为您可以使用模拟 Web 服务器对此进行测试,例如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();
    }
    

    如果您排队另一个 MockResponse带有状态码 429 ,验证将失败,与例如相同错误代码 500 .

    关于rx-java - 如何测试 Spring WebClient 何时重试?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57959242/

    相关文章:

    spring - 在RxJava Services中管理事务性的正确方法是什么?

    java - 什么是分组通量以及我们如何使用分组通量?

    java - 为什么额外的 log() 会影响用于计算 fromCallable() 的线程池?

    android - 在RxAndroid(Observable)中添加subscription到disposable后,控制流结束,没有调用subscribe..!

    java - RxJava/Rx绑定(bind) : how to handle errors on RxView

    android - 带有 View 列表的链式动画 RxJava2 Android

    java - 按需执行热 Observable

    kotlin - 在 Kotlin 中使用 Reactor 分页 Gitlab API

    java - CompletableFuture then 异常后撰写

    android - 销毁 Activity 时在订阅外注销 BroadcastReceiver