英文:
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(<flux>)
.expectSubscription()
.consumeNextWith(e-> log.debug(e.toString()))
.thenAwait().verifyComplete();
will need the following dependency
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<scope>test</scope>
</dependency>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论