当前位置: 首页 > 知识库问答 >
问题:

块()/块第一()/块最后()是阻塞的,这在线程反应器中不受支持

程阳平
2023-03-14

我正在尝试使用WebTest客户端发布数据,但不幸的是,这样的消息被抛出:

java.lang.AssertionError: Status expected:<200> but was:<500>

> POST http://localhost:41087/movie
> Accept: [application/json;charset=UTF-8]
> WebTestClient-Request-Id: [1]
> Content-Type: [application/json;charset=UTF-8]
> Content-Length: [101]

{"movieId":1,"title":"Title for movie 1","genre":"Genre for movie 1","address":"Address for movie 1"}

< 500 INTERNAL_SERVER_ERROR Internal Server Error
< Content-Type: [application/json;charset=UTF-8]
< Content-Length: [226]

{"timestamp":"2020-01-03T10:02:18.467+0000","path":"/movie","status":500,"error":"Internal Server Error","message":"block()/blockFirst()/blockLast() are blocking, which is not supported in thread reactor-http-server-epoll-18"}


    at org.springframework.test.web.reactive.server.ExchangeResult.assertWithDiagnostics(ExchangeResult.java:200)
    at org.springframework.test.web.reactive.server.StatusAssertions.isEqualTo(StatusAssertions.java:59)
    at org.springframework.test.web.reactive.server.StatusAssertions.isEqualTo(StatusAssertions.java:51)
    at com.geborskimateusz.microservices.core.movie.MovieServiceApplicationTests.postAndVerify(MovieServiceApplicationTests.java:111)
    at com.geborskimateusz.microservices.core.movie.MovieServiceApplicationTests.getMovieNotFound(MovieServiceApplicationTests.java:58)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:515)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:115)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$6(TestMethodTestDescriptor.java:171)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:72)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:167)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:114)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:59)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:105)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:72)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:95)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:71)
    at java.util.ArrayList.forEach(ArrayList.java:1257)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:110)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:72)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:95)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:71)
    at java.util.ArrayList.forEach(ArrayList.java:1257)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:110)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:72)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:95)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:71)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:220)
    at org.junit.platform.launcher.core.DefaultLauncher.lambda$execute$6(DefaultLauncher.java:188)
    at org.junit.platform.launcher.core.DefaultLauncher.withInterceptedStreams(DefaultLauncher.java:202)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:181)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:128)
    at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:69)
    at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: java.lang.AssertionError: Status expected:<200> but was:<500>
    at org.springframework.test.util.AssertionErrors.fail(AssertionErrors.java:55)
    at org.springframework.test.util.AssertionErrors.assertEquals(AssertionErrors.java:82)
    at org.springframework.test.web.reactive.server.StatusAssertions.lambda$isEqualTo$0(StatusAssertions.java:59)
    at org.springframework.test.web.reactive.server.ExchangeResult.assertWithDiagnostics(ExchangeResult.java:197)
    ... 43 more

为什么会这样?,我不能阻止值,还是邮政编码有问题?我对这种反应式抽象完全陌生,WebTestClient的这种实现使用了非反应式方法。以下是失败的代码:

这里postAndVerify失败:

@ExtendWith(SpringExtension.class)
@SpringBootTest(webEnvironment = RANDOM_PORT, properties = {"spring.data.mongodb.port: 0"})
public class MovieServiceApplicationTests {

    @Autowired
    WebTestClient webTestClient;

    @Autowired
    MovieRepository movieRepository;


    @Test
    public void getMovie() {
        Integer given = 1;

        postAndVerify(given, HttpStatus.OK);


        getAndVerify(given, HttpStatus.OK)
                .jsonPath("$.movieId").isEqualTo(given)
                .jsonPath("$.genre").isNotEmpty()
                .jsonPath("$.title").isNotEmpty()
                .jsonPath("$.address").isNotEmpty();

    }

    private WebTestClient.BodyContentSpec postAndVerify(Integer id, HttpStatus httpStatus) {
        Movie movie = Movie.builder()
                .movieId(id)
                .title("Title for movie " + id)
                .genre("Genre for movie " + id)
                .address("Address for movie " + id)
                .build();

        return webTestClient.post()
                .uri("/movie")
                .body(Mono.just(movie), Movie.class)
                .accept(MediaType.APPLICATION_JSON_UTF8)
                .exchange()
                .expectStatus().isEqualTo(httpStatus)
                .expectHeader().contentType(MediaType.APPLICATION_JSON_UTF8)
                .expectBody();
    }

}

创建方法的实现如下所示:

@Override
public Movie createMovie(Movie movie) {
    MovieEntity movieEntity = movieMapper.apiToEntity(movie);

    Mono<Movie> movieMono = movieRepository.save(movieEntity)
            .onErrorMap(DuplicateKeyException.class, ex -> new InvalidInputException("Duplicate key for movieId: " + movie.getMovieId()))
            .log()
            .map(movieMapper::entityToApi);

    return movieMono.block();
}

共有2个答案

马业
2023-03-14

请阅读这个答案。它应该有帮助。

正如托马斯所提到的,阻止非阻塞API不是一个好主意。

宇文鸿振
2023-03-14

反应式方法用于非阻塞应用程序。您选择使用反应式是因为您不想阻塞,但您仍然这样做。

解决方案很简单。在反应式应用程序中永远不要调用block。

return movieMono.block();

从您的<code>createMovie</code>中,您应该返回<code>Mono

 类似资料: