WebClient causes "java.lang.IllegalStateException: executor not accepting a task" in JUnit

huangapple go评论95阅读模式
英文:

WebClient causes "java.lang.IllegalStateException: executor not accepting a task" in JUnit

问题

我想在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);
            });
  }

来获取我所有的GitHub仓库。但我一直捕获到以下错误:

java.lang.IllegalStateException: executor not accepting a task

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

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

非常感谢。

英文:

I wanted to use reactive programming inside the JUnit testing framework to do system tests on a remote rest api.

I thus wrote:

  @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  );
            });
  }

to get all my github repos. I kept catching this error:

java.lang.IllegalStateException: executor not accepting a task

until add ".block()" after ".exchange()" to do the call synchronously and everything start to work fine.

I suspect JUnit to start a special thread context or something like that. Do you know what can is happening?

Thanks a lot

答案1

得分: 7

问题在于一旦函数testWebClient()执行完毕,所有的异步进程都被关闭。

在这种情况下,您正在使用WebClient,它是一个异步作业,因此函数testWebClient()会在WebClient获得答案之前就结束了。

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

  • 使用线程休眠方法,比如TimeUnit.SECONDS.sleep(5)
  • 使用一个外部库,比如Awaitility

使用 Awaitility 的示例

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

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

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

英文:

The problem is that once the function testWebClient() finish, all the asynchronous process are closed.

In this case you are using WebClient that is an async job, so the function testWebClient() finish before the WebClient can get the answer.

In order to prevent this, you can:

  • use a thread sleep method like TimeUnit.SECONDS.sleep(5).
  • use an external library like Awaitility

Example with Awaitility


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

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

So in this case the function will wait until the task complete.

答案2

得分: 0

另一种选择是在测试用例中使用 StepVerifier。

    StepVerifier.create(<flux>)
      .expectSubscription()
      .consumeNextWith(e-> log.debug(e.toString()))      
      .thenAwait().verifyComplete();

需要以下依赖:

	<dependency>
		<groupId>io.projectreactor</groupId>
		<artifactId>reactor-test</artifactId>
		<scope>test</scope>
	</dependency>
英文:

Another option is to use StepVerifier in your test case.

    StepVerifier.create(&lt;flux&gt;)
      .expectSubscription()
      .consumeNextWith(e-&gt; log.debug(e.toString()))      
      .thenAwait().verifyComplete();

will need the following dependency

	&lt;dependency&gt;
		&lt;groupId&gt;io.projectreactor&lt;/groupId&gt;
		&lt;artifactId&gt;reactor-test&lt;/artifactId&gt;
		&lt;scope&gt;test&lt;/scope&gt;
	&lt;/dependency&gt;

huangapple
  • 本文由 发表于 2020年9月22日 09:49:12
  • 转载请务必保留本文链接:https://go.coder-hub.com/64002009.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定