This post has helped me to send CSV output from a controller when the desired media type is specified as a URL parameter. Here’s my configuration class that does this:
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.lang.NonNull;
import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import com.fasterxml.jackson.databind.ObjectMapper;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
private ObjectMapper objectMapper;
@Override
public void configureContentNegotiation(@NonNull final ContentNegotiationConfigurer configurer) {
configurer
.favorParameter(true)
.parameterName("format")
.ignoreAcceptHeader(false)
.defaultContentType(MediaType.APPLICATION_JSON)
.mediaType("csv", MediaType.parseMediaType("application/csv"))
.mediaType("xml", MediaType.APPLICATION_XML)
.mediaType("json", MediaType.APPLICATION_JSON);
}
@Override
public void extendMessageConverters(@NonNull List<HttpMessageConverter<?>> converters) {
converters.add(new CsvConverter<>(objectMapper));
}
}
The class CsvConverter
is as described in the SO post referenced above.
Now I am trying to write a test that verifies my Spring configuration is correct. My understanding of https://docs.spring.io/spring-framework/reference/testing/webtestclient.htm indicates I should be able to use bindToController
to do this, as the required configuration should be loaded.
Here’s the essence of the test code I used:
@SpringBootTest()
@ActiveProfiles(profiles = "dev")
public class PersonControllerTest {
@Test
public void testGetPersonEnrollmentReturnsCSVWhenFormatParameterPresent() {
var personController = new PersonController(
classService, mock(PersonService.class), enrollmentService, attendanceService
);
WebTestClient client = WebTestClient.bindToController(personController).build();
client.get()
.uri("/api/person/get/enrollments/1?format=csv")
.exchange()
.expectStatus().isOk()
.expectHeader().contentType("application/csv");
}
}
When this test is run, it fails since the content type is application/json instead of the expected application/csv. I have verified that the code in my WebConfig.java
configuration is being executed.
If I change the creation of the WebClient
to look like this:
WebTestClient client = WebTestClient.bindToServer().baseUrl("https://localhost:8080").build();
and test against the running server, I get the expected content type.
What am I missing using bindToController
to make the test run without needing a running server?