问题描述
我一直在尝试实现Spring反应式路由器和处理程序,而不是MVC控制器。看起来很简单,但是我的WebTestClient测试由于500 Internal Server Error而失败。测试的代码短码。
@ContextConfiguration(classes = {FooRouter.class,FooServiceConfig.class,FoonHandler.class})
@WebFluxTest
public class FooHandlerTest {
@Test
public void testFooPost() {
webTestClient.post()
.uri("/foot")
.contentType(MediaType.APPLICATION_XML)
.accept(MediaType.APPLICATION_XML)
.body(Mono.just(foo),Foo.class)
.exchange()
.expectStatus().isCreated()
.expectBody(Bar.class)
.isEqualTo(bar);
}
在测试过程中,路由器工作正常并调用处理程序。当处理程序尝试从请求正文创建Mono时:
Mono<Foo> fooMono = request.bodyToMono(Foo.class);
该行杀死了单元测试,并且WebTestClient收到500状态代码。在调试期间,尽管mime类型是application / xml,并且确实映射了Java类,但BodyExtractors仍在过滤解码器并匹配类和mime类型。对于Json,它正在查看Java类,并在比较mime类型之前尝试从中获得映射。深入调试时,当它仍尝试将类映射到对象映射器时,它将崩溃。
我目前正在将Spring Boot版本2.3.4-RELEASE与Java8结合使用。文档中提到如果您的类路径中有JaxB,则对于XML,应使用Jaxb2XmlDecoder和Endoder作为默认编解码器。如果您在类路径中使用了Jackson,它也将使用Jackson。我确实碰巧都减去了jackson-dataformat-xml依赖项。我很确定这是我的测试配置,也可以是WebFluxConfigurer,我尝试为jaxb2Decoder和Encoder设置默认编解码器。我也曾尝试添加jackson-dataformat-xml依赖项,但这也不起作用。这是我尝试使用的webconfig,但是尝试使用Json解码器解码application / xml的mime类型仍然失败。这是webconfig:
@Configuration
@EnableWebFlux
public class WebConfig implements WebFluxConfigurer {
@Override
public void configureHttpMessageCodecs(ServerCodecConfigurer configurer) {
configurer.registerDefaults(false);
configurer.defaultCodecs().jaxb2Decoder(new Jaxb2XmlDecoder(MediaType.APPLICATION_XML));
configurer.defaultCodecs().jaxb2Encoder(new Jaxb2XmlEncoder());
}
}
我一直在调试并打印出请求对象消息阅读器,而Jaxb2XmlEncoder是xml mime类型的编解码器之一。这是JSON和XML解码器的打印消息:
Message Reader: org.springframework.http.codec.DecoderHttpMessageReader@5b2cea27
DecoderHttpMessageReader Decoder: org.springframework.http.codec.json.Jackson2JsonDecoder@87b7472
Mime Type: application/json
Mime Type: application/*+json
Message Reader: org.springframework.http.codec.DecoderHttpMessageReader@198a86e1
DecoderHttpMessageReader Decoder: org.springframework.http.codec.xml.Jaxb2XmlDecoder@50cb41d0
Mime Type: application/xml
Mime Type: text/xml
Mime Type: application/*+xml
在BodyExtractors类的readWithMessageReaders方法中,函数中有一个筛选器,该筛选器遍历消息阅读器和解码器。当到达DecoderHttpMessageReader,Jackson2JsonDecoder时,它开始尝试对请求进行解码。不知道为什么,因为调试器中的mime类型显示application / xml。
有人对如何调试这段代码有任何建议吗?
Mono<Foo> fooMono = request.bodyToMono(Foo.class);
这是上面代码在单元测试期间死亡的地方。我已经尝试过调试,但是当我变得太深时,它只会停止测试。我只知道它在尝试匹配编解码器时正在经历Java类型。大多数编解码器会立即返回,但是Json和XML解码器正在尝试获取Java类属性并且令人窒息。该类是具有所有正确批注的JaxB类。 WebTestClient毫无疑问地将类编码为XML以进行测试。那么,处理程序为什么不能将主体转换为单声道呢?该代码语句什么也没扔。
解决方法
我知道这是我的设置,单元测试未显示正确的问题。
我的return语句实际上在获取正文内容时导致错误。
旧的退货声明:
return created(URI.create(response.getDocument().getPath()))
.bodyValue(Mono.just(response));
新的退货声明:
return created(URI.create(response.getDocument().getPath()))
.body(Mono.just(response),Response.class);
看到bodyValue和body的区别了吗?这导致请求主体无法转换为Mono。