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

Time:06-04

In my spring boot app, I want to write a web-test.

My application returns a list of strings. The test however produces a list with only one element (complete json as string).

My (minimal example) production code:

@SpringBootApplication
public class BackendApplication {

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

}

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

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

My test class:

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

    @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);
    }
}

My maven dependencies (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>

The test fails:

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

However, if I access the production application via postman, I receive:

["Fruits","Regional"]

Why does the reactive WebTestClient not parse this json, but instead create an array with only one string? How can I tell it to parse the string and give me a list of strings (with my two items as elements) instead?

CodePudding user response:

If you replace

.expectBodyList(String.class)

by

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

it works. Like this:

@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);
}

CodePudding user response:

Check the default behaviour of Jackson2Decoder of Spring WebClient

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

For a multi-value publisher, WebClient by default collects the values with Flux#collectToList() and then serializes the resulting collection.

You will need to deserialize accordingly.

  • Related