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
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.