MockMVC perform post test to async service

2019-07-18 16:08发布

问题:

I need to test a controller which calls an asynchronous service.

CONTROLLER CODE

@RequestMapping(value = "/path", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public ResponseEntity<Result> massiveImport(HttpServletRequest request) {
    try {
        service.asyncMethod(request);
    } catch (Exception e) {
        e.printStackTrace();
        return new ResponseEntity<>(new Result(e.getMessage()), HttpStatus.BAD_REQUEST);
    }

    return new ResponseEntity<>(new Result(saveContact.toString()), HttpStatus.OK);
}

SERVICE CODE

@Async
public Future<Integer> asyncMethod(HttpServletRequest request) throws IllegalFieldValueException, Exception {
    ...
    return new AsyncResult<>(value);
}

TEST CODE

MvcResult result = getMvc().perform(MockMvcRequestBuilders.fileUpload("/path/")
                           .header("X-Auth-Token", accessToken)
                           .accept(MediaType.APPLICATION_JSON))
                           .andDo(print())
                           .andReturn();

Test is ok. But I would wait, before closing the test, to complete async service.

Is there any way to do this?

回答1:

If you just want to wait for the async execution to be finished have look at MvcResult. You can wait for it with getAsyncResult().

With your current code you are just performing the request without any assertions. So the test is not complete. For a complete test it takes the following two steps.

First perform the request:

MvcResult mvcResult = getMvc().perform(fileUpload("/path/")
                              .header("X-Auth-Token", accessToken)
                              .accept(MediaType.APPLICATION_JSON))
                              .andExpect(request().asyncStarted())
                              .andReturn();

Then start the async dispatch via asyncDispatch and perform assertions:

getMvc().perform(asyncDispatch(mvcResult))
        .andExpect(status().isOk())
        .andExpect(content().contentType(...))
        .andExpect(content().string(...));