gpt4 book ai didi

java - MockMvc 是否有资格进行 WebFlux Controller 测试?

转载 作者:行者123 更新时间:2023-11-30 01:46:54 27 4
gpt4 key购买 nike

我有一个简单的 WebFlux 应用程序(使用 Controller ,而不是路由器功能)。唯一的非标准部分是它使用 Server-Sent-Events。

Controller 的一个有趣的部分是

    @GetMapping(path = "/persons", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<ServerSentEvent<Object>> persons() {
return service.persons()
.map(this::personToSse)
.onErrorResume(e -> Mono.just(throwableToSse(e)));
}

private ServerSentEvent<Object> personToSse(Person person) {
return ServerSentEvent.builder().data(person).build();
}

服务:

public interface Service {
Flux<Person> persons();
}

我有两个测试:

@SpringBootTest(classes = Config.class)
@AutoConfigureMockMvc
class PersonsControllerTest {
@Autowired
private MockMvc mockMvc;

@MockBean
private Service service;

@Test
void streamsPersons() throws Exception {
when(service.persons())
.thenReturn(Flux.just(new Person("John", "Smith"), new Person("Jane", "Doe")));

String responseText = mockMvc.perform(get("/persons").accept(MediaType.TEXT_EVENT_STREAM))
.andExpect(status().is2xxSuccessful())
.andExpect(content().string(not(isEmptyString())))
.andReturn()
.getResponse()
.getContentAsString();

assertThatJohnAndJaneAreReturned(responseText);
}

@Test
void handlesExceptionDuringStreaming() throws Exception {
when(service.persons())
.thenReturn(Flux.error(new RuntimeException("Oops!")));

String responseText = mockMvc.perform(get("/persons").accept(MediaType.TEXT_EVENT_STREAM))
.andExpect(status().is2xxSuccessful())
.andReturn()
.getResponse()
.getContentAsString();

assertThat(responseText, is("event:internal-error\ndata:Oops!\n\n"));
}

第一个测试检查“晴天场景”中我们是否得到了我们期望的两个人。第二个测试检查异常发生时会发生什么。

当我一项一项地运行测试时,它们运行得很好。但是当我运行它们时,有时它们会通过,有时其中之一会失败,有时两者都会失败。失败原因不同:

  1. 有时 Jackson 在 JSON 解析过程中提示达到了 EOF(“由于输入结束而没有要映射的内容”,尽管在日志中我可以看到有效的完整 JSON)
  2. 有时第一个测试失败,第二个测试通过,就好像在这两种情况下都返回了错误,即使我可以在日志中看到第一个测试生成了正常响应,而不是错误的响应
  3. 有时第二次测试失败,第一次测试通过,就好像在这两种情况下都返回了有效的 JSON

看来存在一些并发问题。但我的测试代码足够简单,没有使用任何并发相关的概念。

以下测试在我的机器上 100% 失败(它只是重复运行这 2 个测试 1000 次):

    @Test
void manyTimes() throws Exception {
for (int i = 0; i < 1000; i++) {
streamsPersons();
handlesExceptionDuringStreaming();
}
}

问题如下:

  1. MockMvc 可以用来测试响应式(Reactive) Controller 吗?
  2. 如果可以的话,我是否做错了什么?

这里是完整的项目源代码:https://github.com/rpuch/sse-webflux-testsmanyTests() 方法已被注释掉,必须重新启用才能使用。

最佳答案

<强>1。 MockMvc 可以用来测试响应式(Reactive) Controller 吗?

答案是否定的,MockMvc是一个阻塞的mockClient,它将调用你的方法一次并返回。它无法在发出项目时连续读取项目。您需要使用的客户端是 Spring WebClient

您可以在此处了解更多如何操作 testing infinite streams使用 Spring WebTestClient

<强>2。如果可以的话,我是否做错了什么?

查看问题一的答案。

关于java - MockMvc 是否有资格进行 WebFlux Controller 测试?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57631829/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com