我有一个端点将org.springframework.http.server.reactive.ServerHttpResponse
转换为org.springframework.http.ZeroCopyHttpOutputMessage
。
@SneakyThrows
@GetMapping("/document/{documentId}")
public Mono<Void> serveDocument(@PathVariable final String documentId, final ServerHttpResponse response) {
final Path documentLocation = fileManipulatorService.newFile(stagingConfigurationProperties.location(), documentId);
return ((ZeroCopyHttpOutputMessage) response)
.writeWith(documentLocation, 0, fileManipulatorService.size(documentLocation))
.then(deleteIfExists(documentLocation));
}
通常情况下,这可以很好地工作,但是当使用org.springframework.test.web.reactive.server.WebTestClient
调用端点时,调用会失败,并出现以下异常:
2022-12-30T18:49:07.678+01:00 ERROR 1392 --- [ parallel-1] a.w.r.e.AbstractErrorWebExceptionHandler : [1848ca22] 500 Server Error for HTTP GET "/document/11c92bad-6fe4-4c85-9d54-4bf4bbad3581"
java.lang.ClassCastException: class org.springframework.mock.http.server.reactive.MockServerHttpResponse cannot be cast to class org.springframework.http.ZeroCopyHttpOutputMessage (org.springframework.mock.http.server.reactive.MockServerHttpResponse and org.springframework.http.ZeroCopyHttpOutputMessage are in unnamed module of loader 'app')
at com.github.bottomlessarchive.loa.stage.view.document.controller.StageDocumentController.serveDocument(StageDocumentController.java:53) ~[main/:na]
Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
Error has been observed at the following site(s):
*__checkpoint ? HTTP GET "/document/11c92bad-6fe4-4c85-9d54-4bf4bbad3581" [ExceptionHandlingWebHandler]
这是我的测试结果:
@Test
void testServeDocument() {
final UUID documentId = UUID.randomUUID();
final byte[] content = {1, 2, 3, 4};
final Path contentPath = setupFakeFile("/stage/" + documentId, content);
when(fileManipulatorService.newFile("/stage/", documentId.toString()))
.thenReturn(contentPath);
final byte[] responseBody = webTestClient.get()
.uri("/document/" + documentId)
.exchange()
.expectStatus()
.isOk()
.expectBody()
.returnResult()
.getResponseBody();
assertThat(responseBody)
.isEqualTo(content);
assertThat(contentPath)
.doesNotExist();
}
对我来说,一切似乎都是正确的。MockServerHttpResponse不扩展ZeroCopyHttpOutputMessage有什么原因吗?因为这个原因,我想向Sping Boot 提交一个bug报告,但在这样做之前,我得出结论,首先询问Stackoverflow可能是一个更好的主意。
1条答案
按热度按时间ni65a41a1#
首先,
MockServerHttpResponse
是测试响应的通用模拟实现,没有实际的服务器,因此它的实现方式足以方便测试。其次,看起来没有任何保证
ServerWebExchange
中的响应必须实现ZeroCopyHttpOutputMessage
,所以我不会在没有预先类型检查的情况下盲目地强制转换它。另一个警告是,在Netty上,即使响应是
ZeroCopyHttpOutputMessage
,只有当指定的路径解析为本地文件系统File
时,传输才会使用零字节拷贝,并且压缩和SSL/TLS未启用,否则将使用分块读/写。( https://projectreactor.io/docs/netty/release/api/reactor/netty/NettyOutbound.html#sendFile-java.nio.file.Path-long-long- ).
考虑到所有这些,我将把你的控制器重构成这样:
要在集成测试中测试此控制器的
ZeroCopyHttpOutputMessage
部分,您可以使用真实(非模拟)Web环境,并将WebTestClient
绑定到该环境,如下所示: