Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Boot does not register HttpMessageConverter during test run

I'm running a Spring Boot app and I've registered a new HttpMessageConverter called CsvCompactVenueHttpMessageConverter, here's the code for it:

@Component
public class CsvCompactVenueHttpMessageConverter extends
    AbstractHttpMessageConverter<Collection<CompactVenue>> {

    public CsvCompactVenueHttpMessageConverter() {
       super(MediaType.valueOf(TEXT_CSV));
    }

   >> message converter implementation code <<
}

It extends AbstractHttpMessageConverter and is registered as a bean on class WebConfiguration:

@Configuration
public class WebConfiguration extends WebMvcConfigurerAdapter {

    @Bean
    public CsvCompactVenueHttpMessageConverter csvCompactVenueHttpMessageConverter() {
        return new CsvCompactVenueHttpMessageConverter();
    }
}

Then I have a rest resource called FoursquareResource:

@RestController
@RequestMapping("/foursquare")
public class FoursquareResource {

    @Autowired
    FoursquareService foursquareService;

    @GetMapping(value = "/{location}", produces = {"application/json", "text/csv"})
    public Collection<CompactVenue> searchVenuesByLocationAndIncreasingRange(@PathVariable String location, @RequestParam(defaultValue = "1") Integer numQueries) throws FoursquareApiException, FoursquareServiceException {
        return foursquareService.searchVenuesByLocationAndIncreasingRange(location, numQueries);
    }
}

When I run the app and call http://localhost:8080/foursquare/New York NY it works fine and renders the text/csv response.

But when running the test with RestAssured and @SpringBootTest I get a HTTP 406 response (because I think it did not register correctly the HttpMessageConverter for text/csv), here's the code:

@RunWith(SpringRunner.class)
@SpringBootTest
@Slf4j
public class FoursquareResourceTest {

    @Mock
    FoursquareService foursquareService;

    @InjectMocks
    FoursquareResource foursquareResource;

    @Before
    public void before() throws Exception {
        CompactVenue venue = new CompactVenue();
        FieldUtils.writeField(venue, "id", "aUfmEW745", true);
        Collection<CompactVenue> venues = new ArrayList<>();
        venues.add(venue);
        when(foursquareService.searchVenuesByLocationAndIncreasingRange(any(), any())).thenReturn(venues);
    }

    @Test
    public void testSearchVenuesByLocationAndIncreasingRangeCsv() throws Exception {
        MockMvcResponse response =
        given().
            accept("text/csv").
            standaloneSetup(foursquareResource).
        when().
            get(String.format("/foursquare/%s?numQueries=%d",location,numQueries)).
        then().
            statusCode(200).
        extract().response();

        log.info(response.body().print());
    }

}

I'm not sure why do I get a right answer when running the Spring Boot app but the 406 error when running as a Test. It looks like the new HttpMessageConverter is not registered on the tests but I can't see why. Thanks and regards.

like image 723
Bruno Leite Avatar asked Feb 25 '26 20:02

Bruno Leite


1 Answers

406 Not Acceptable just means that the controller is not able to serve the representation, requested by the client. In your case the client indicates its capability to read text/csv by sending Accept header, but the controller is not able to send text/csv back. Most probably lacking your converter. To understand why, it is important to understand one thing about MockMvc. It is not clear, how your MockMvc is initialized, but I assume it is standalone setup. Be aware that standaloneSetup creates a new application context, where the beans from you standard configurations are not registered, including your custom converter. This explains, why the code works in a "normal" run, but fails in test. To overcome this, either use webAppContextSetup (which will start the application and embedded Jetty/Tomcat) with injected application context or manually set the converters by calling setMessageConverters on StandaloneMockMvcBuilder. For example,

mockMvc = MockMvcBuilders
        .standaloneSetup(controller)
        .setMessageConverters(new SomeConverter(),
                new SomeOtherConverter())
        .build();

You can then reuse the mockMvc object in your REST Assure just by calling

RestAssuredMockMvc.mockMvc(mockMvc);
like image 197
The Ancient Avatar answered Feb 27 '26 10:02

The Ancient