WebClient 在 JUnit 中导致“java.lang.IllegalStateException:执行器不接受任务”

Gui*_*het 3 java spring spring-webclient

我想在 JUnit 测试框架内使用反应式编程来对远程 REST API 进行系统测试。

我因此写道:

  @Test
  void testWebClient() {
    WebClient webClient = WebClient.builder()
        .baseUrl(GITHUB_API_BASE_URL)
        .defaultHeader(HttpHeaders.CONTENT_TYPE, GITHUB_V3_MIME_TYPE)
        .defaultHeader(HttpHeaders.USER_AGENT, USER_AGENT)
        .filter(ExchangeFilterFunctions
            .basicAuthentication(appProperties.getGithub().getUsername(),
                appProperties.getGithub().getToken()))
        .build();

    var response = webClient.get()
        .uri("/user/repos?sort={sortField}&direction={sortDirection}",
            "updated", "desc")
        .exchange()
            .doOnError(e -> {
              System.out.println(e.toString());
            })
            .subscribe(r -> {
              System.out.println(r  );
            });
  }
Run Code Online (Sandbox Code Playgroud)

获取我所有的 github 存储库。我不断发现这个错误:

java.lang.IllegalStateException: executor not accepting a task
Run Code Online (Sandbox Code Playgroud)

直到在“.exchange()”之后添加“.block()”以同步进行调用,一切开始正常工作。

我怀疑 JUnit 会启动一个特殊的线程上下文或类似的东西。你知道发生了什么吗?

多谢

小智 8

问题是,一旦函数testWebClient()完成,所有异步进程都会关闭。

在这种情况下,您使用的WebClient是异步作业,因此该函数在获得答案testWebClient()之前完成。WebClient

为了防止这种情况,您可以:

  • 使用线程睡眠方法,例如TimeUnit.SECONDS.sleep(5).
  • 使用外部库,例如Awaitility

等待示例


bool taskDone = false;
@Test
void testWebClient() {
    //...
    var response = webClient.get()
    //...
    .doFinally(r->{
        taskDone = true;
    })

    await().until(()-> taskDone);
}

Run Code Online (Sandbox Code Playgroud)

因此在这种情况下,该函数将等待任务完成。

  • 使用 sleep 或外部库的另一个选择是让 Web 客户端调用阻塞调用。您的代码可能是这样的:`var resp = webClient.get().uri(url).retrieve().toEntity(String.class).block(); assertEquals(HttpStatus.OK, resp.getStatusCode());` (2认同)