4

I am trying to use MockMvc to test my Spring 4.1 controller with an async result. I have followed the same pattern as described here:

https://github.com/spring-projects/spring-mvc-showcase/blob/master/src/test/java/org/springframework/samples/mvc/async/DeferredResultControllerTests.java

However, my test is different, as I am using a return value handler as described here:

https://github.com/AndreasKl/spring-boot-mvc-completablefuture

Here is what my test code looks like:

public class MyControllerTest {

        private MockMvc mockMvc;
        private MyService myService;
        private MyController myController;

        public MappingJackson2HttpMessageConverter createMessageConverter() {

            ObjectMapper objectMapper = new ObjectMapper();
            List<MediaType> supportedMediaTypes = Arrays.asList(MediaTypes.JSON_V1);

            MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
            converter.setObjectMapper(objectMapper);
            converter.setSupportedMediaTypes(supportedMediaTypes);

            return converter;
        }

        @Before
        public void setup() throws Exception {   

            MappingJackson2HttpMessageConverter converter = createMessageConverter();
            myService = mock(MyService.class);

            controller = new MyController(myService);

            mockMvc = MockMvcBuilders.standaloneSetup(controller)
                .setMessageConverters(converter)
                .setCustomReturnValueHandlers(new CompletableFutureReturnValueHandler())
                .build();
        }

        @Test
        public void test() throws Exception {

            String value = "foo";
            CompletableFuture<ExampleData> futureValue = 
                CompletableFuture.completedFuture(new ExampleData(value));

            when(myService.getExample()).thenReturn(futureValue);

            MvcResult mvcResult = mockMvc.perform(get("/example"))
                .andExpect(status().isOk())
                .andExpect(request().asyncStarted())
                .andExpect(request().asyncResult(instanceOf(ExampleData.class)))
                .andReturn();

            mockMvc.perform(asyncDispatch(mvcResult))
                .andExpect(status().isOk())
                .andExpect(content().contentType(MediaTypes.JSON_V1_VALUE))
                .andExpect(jsonPath("$.property", is(value)));
        }
}

It seems that even if I set the return value handler by using StandaloneMockMvcBuilder.setCustomReturnValueHandlers(), it is never called. This results in the assertion for request().asyncStarted() to fail because the result is not a Callable or DeferredResult.

Am I setting up the handler correctly or is there something else missing?

==== SOLUTION ======

After reading through the documentation and stepping through with the debugger I found that setCustomReturnValueHandlers() adds the handlers to the end of the list, while the spring-boot-mvc-completablefuture example inserts it before the DeferredResult hander. Using the non-standalone mode would allow this.

David Fox
  • 41
  • 4
  • Can you explain your solution in more detail? "Using the non-standalone mode would allow this". I don't really get that. I am having the same problem. – Disco Mike Aug 09 '19 at 18:33

0 Answers0