Spring MockMvc and asynchronous controller HTTP status code

How to check / test internal server 500 error in MockMvc when my controller has Async servlet nature ?

I am writing unit test for my REST endpoint as part of test cases, I need to check that the server is sending 500 internal errors as an http code and with the corresponding error message.

Here is my spring boot application: (all imports are excluded for better readability)

@RestController @RequestMapping("/user") @EnableAutoConfiguration @SpringBootApplication public class App { @RequestMapping(method = RequestMethod.GET, value = "/{name}", produces = MediaType.APPLICATION_JSON_VALUE) private DeferredResult<String> greetByJson(@PathVariable("name") final String name){ DeferredResult<String> dResult = new DeferredResult<String>(); new Thread(new Runnable() { @Override public void run() { try { Thread.sleep(5000); dResult.setErrorResult(new RuntimeException("Boom!!! time for Internal server error")); } catch (InterruptedException e) { e.printStackTrace(); } } }).start(); return dResult; } public static void main( String[] args ) { SpringApplication.run(App.class); } } 

Here are my test cases for MovkMvc JUnit:

 @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = MockServletContext.class) @WebAppConfiguration public class AppTest { private final MockMvc mockMvc = MockMvcBuilders.standaloneSetup(new App()) .build(); @Test public void testAsyncInternalServerError() { try { MvcResult mvcResult = mockMvc.perform( get("/user/naveen").accept(MediaType.APPLICATION_JSON_VALUE)) .andExpect(request().asyncStarted()) .andReturn(); System.out.println("Http Response Content = " + mvcResult.getAsyncResult()); System.out.println("Http Response Status Code = " + mvcResult.getResponse().getStatus()); } catch (Exception e) { e.printStackTrace(); } } } 

The following are console prints:

 2015-08-08 18:11:51.494 INFO 10224 --- [ main] oswcsGenericWebApplicationContext : Refreshing org.s pringframework.web.context.support.GenericWebApplicationContext@ a82c5f1: startup date [Sat Aug 08 18:11:51 IST 2015]; root of context hierarchy 2015-08-08 18:11:51.526 INFO 10224 --- [ main] oejijunit.runner.RemoteTestRunner : Started RemoteTestRunner in 0.258 seconds (JVM running for 1.131) Http Response Content = java.lang.RuntimeException: Boom!!! time for Internal server error Http Response Status Code = 200 2015-08-08 18:11:56.584 INFO 10224 --- [ Thread-1] oswcsGenericWebApplicationContext : Closing org.s pringframework.web.context.support.GenericWebApplicationContext@ a82c5f1: startup date [Sat Aug 08 18:11:51 IST 2015]; root of context hierarchy 

From the above log you can see that MockMvc returns an http status code as 200 not 500. The error message is just fine.

Where, when I call the endpoint using the Chrome mailbox, I see 500 internal server errors, as shown in the figure enter image description here

+4
source share
3 answers

You should do asynchronous submission and then check the status:

 @Test public void testMethod() throws Exception { MvcResult mvcResult = mockMvc.perform(get("/your/endpoint")) .andExpect(request().asyncStarted()) .andExpect(request().asyncResult(notNullValue())) .andReturn(); mockMvc.perform(asyncDispatch(mvcResult)) .andExpect(status().isInternalServerError()) .andReturn(); } 
+8
source

A custom perform helper method that processes both a synchronization request and an asynchronous request:

 ResultActions perform(MockHttpServletRequestBuilder builder) throws Exception { ResultActions resultActions = mockMvc.perform(builder); if (resultActions.andReturn().getRequest().isAsyncStarted()) { return mockMvc.perform(asyncDispatch(resultActions .andExpect(request().asyncResult(anything())) .andReturn())); } else { return resultActions; } } 

A longer answer with an example here

+1
source

The following is a working example (Groovy Spock Specification) using the asyncPerform(builder) method

 import static org.hamcrest.core.IsNull.notNullValue import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.asyncDispatch import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.* @ContextConfiguration(classes = [MyConfig]) @WebAppConfiguration class MyControllerComponentSpec extends Specification { @Autowired WebApplicationContext webApplicationContext MockMvc endpoint def setup() { endpoint = MockMvcBuilders.webAppContextSetup(webApplicationContext).build() } ResultActions asyncPerform(MockHttpServletRequestBuilder builder) throws Exception { ResultActions resultActions = endpoint.perform(builder); asyncDispatch(resultActions.andExpect(request() .asyncResult(notNullValue())) .andReturn())); } def "accepts valid request and responds with 200 status code and response body"() { when: def response = asyncPerform(post("/my_async_endpoint") .content("""{"correlationID": "fe5d1699-20e3-4502-bf51-b947e6b9e51a"}""") .header("Content-Type", "application/json")) .andDo(print()) then: response.andExpect(status().is(200)) .andExpect(jsonPath("body.correlationID").value("fe5d1699-20e3-4502-bf51-b947e6b9e51a")) } } 
0
source

All Articles