如何在 Spring Boot Reactive Webflux 的测试中解析 String[]?

How to parse a String[] in tests with Spring Boot Reactive Webflux?

在我的 spring 启动应用程序中,我想编写一个网络测试。

我的应用程序returns 一个字符串列表。但是,测试会生成一个只有一个元素的列表(完整的 json 作为字符串)。

我的(最小示例)生产代码:

@SpringBootApplication
public class BackendApplication {

    public static void main(String[] args) {
        SpringApplication.run(BackendApplication.class, args);
    }

}

@RestController
@RequestMapping("/allBoxes")
class WhosebugController {

    @GetMapping
    public List<String> getNamesOfAllBoxes() {
        return List.of("Fruits", "Regional");
    }
}

我的测试class:

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class WhosebugControllerTest {

    @Autowired
    WebTestClient webTestClient;

    @Test
    void whenListOfStringsEndpoint_thenExpectListOfStrings(){
        // When
        List<String> actual = webTestClient.get()
                .uri("/allBoxes")
                .exchange()
                .expectStatus().is2xxSuccessful()
                .expectBodyList(String.class)
                .returnResult()
                .getResponseBody();
        // Then

        Assertions.assertEquals(List.of("Fruits", "Regional"), actual);
    }
}

我的 Maven 依赖项(spring boot 2.7.0 parent):

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-webflux</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

测试失败:

org.opentest4j.AssertionFailedError: 
Expected :[Fruits, Regional]
Actual   :[["Fruits","Regional"]]

但是,如果我通过邮递员访问生产应用程序,我会收到:

["Fruits","Regional"]

为什么反应式 WebTestClient 不解析这个 json,而是创建一个只有一个字符串的数组?我怎样才能告诉它解析字符串并给我一个字符串列表(以我的两个项目作为元素)?

检查 Jackson2DecoderSpring WebClient

的默认行为

https://docs.spring.io/spring-framework/docs/current/reference/html/web-reactive.html#webflux-codecs-jackson

对于 multi-value 发布者,WebClient 默认情况下使用 Flux#collectToList() 收集值,然后 serializes 结果集合。

您将需要 deserialize 相应地。

如果你更换

.expectBodyList(String.class)

来自

.expectBody(new ParameterizedTypeReference<List<String>>() {})

有效。像这样:

@Test
void whenListOfStringsEndpoint_thenExpectListOfStrings(){
    // When
    List<String> actual = webTestClient.get()
            .uri("/allBoxes")
            .exchange()
            .expectStatus().is2xxSuccessful()
            .expectBody(new ParameterizedTypeReference<List<String>>() {})
            .returnResult()
            .getResponseBody();
    // Then
    Assertions.assertEquals(List.of("Fruits", "Regional"), actual);
}