Spring WebFluxTest 使用 Flux 作为响应时的奇怪行为<String>



我目前在使用Spring WebFlux测试以下控制器时遇到了一个奇怪的问题(v. 5.2.6(

@RestController
@RequestMapping(path = "/address", produces = MediaType.APPLICATION_JSON_VALUE)
public class AddressController {
@GetMapping(path = "/postcode")
public Flux<String> listPostCodes(...) {
return Flux.just("4711", "4712");
}
@GetMapping(path = "/cities")
public Flux<City> listCities() {
return Flux.just(new City("foo"), new City("bar"));
}
}

该控制器嵌入在"hello world"Spring-Boot应用程序中,使用spring-webflux-starter和一个简单的主类。 类City只有一个属性"名称"。

现在我有以下测试(Junit5(以确保上述控制器的响应

@SpringWebFluxTest
public AddressControllerTest {
@Test
public void postcodes() {
webTestClient.get()
.uri("/address/postcode")
.exchange()
.expectStatus()
.isOk()
.expectBody()
.jsonPath("$")
.isArray()
.jsonPath("$[0]")
.isEqualTo("4711")
}
@Test
public void cities() {
webTestClient.get()
.uri("/address/cities")
.exchange()
.expectStatus()
.isOk()
.expectBody()
.jsonPath("$")
.isArray()
.jsonPath("$[0].name")
.isEqualTo("foo")
}
}

你以为这两个测试都能通过吗?我也是。不幸的是,第一个失败了,告诉我响应正文根不是 json 数组,而是 Long:

Expected: an instance of java.util.List
but: <47114712L> is a java.lang.Long

这是为什么呢?两个响应都是 Flux,所以我希望两个响应体都是一个数组,但前提是元素不是"简单"类型,这似乎在测试中有效。如果我使用邮递员来断言该行为,一切都完全按预期工作,所以我会以某种方式假设测试问题。

有人可以向我解释一下,或者可能有解决方案吗?

提前致谢

这不是测试的问题,实际行为不是您所期望的。

两个响应都是 Flux,所以我希望两个响应体都是一个数组

Flux与列表不同。它是一个数据流,可以逐字输出,也可以在完成后收集到其他数据结构中(列表就是一个例子(。

当然,在这种情况下,指定的内容类型表示您希望在可能的情况下将该Flux收集到列表中 - 但情况并非普遍如此。对于POJO,集合和数组,Jackson将序列化它们,并输出一个数组。但是在这里我们使用原始字符串,而不是对这些字符串使用 JSON 序列化器,所以它只是在它们出现时连接并输出它们。(当然,串联的邮政编码恰好是所有数字,因此您会收到有关long值的错误。

如果你想要一个 JSON 数组,你需要使用:

@GetMapping(path = "/postcode")
public Mono<List<String>> listPostCodes() {
return Flux.just("4711", "4712").collectList();
}

提前用这种方法消除一个常见的神话 - 你不会通过使用collectList()来阻止,并且你不会在幕后丢失任何东西(因为即使你使用Flux,框架仍然需要在内部收集到列表中以返回 JSON 数组。

最新更新