MockMvcRequestBuilders.asyncDispatch, предоставляющий пустой HTTP-ответ и contentType
У меня есть модульный тест, где я пытаюсь проверить ответ на асинхронный запрос, после преобразования метода для возврата StreamingResponseBody с помощью Spring 4.3.
Метод испытания ниже:
final MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(wac)
.apply(SecurityMockMvcConfigurers.springSecurity())
.build();
MvcResult mvcResult1 = mockMvc.perform(
get("/reports/generic/100?FIELD1=&FIELD3=").headers(STANDARD_HEADERS.get()))
.andExpect(status().isOk())
.andExpect(request().asyncStarted())
.andReturn();
mvcResult1.getAsyncResult();
mockMvc.perform(asyncDispatch(mvcResult1))
.andExpect(status().isOk())
.andExpect(content().contentType("text/csv"))
.andExpect(content().string("Test Data" + System.lineSeparator() + "FIELD1=" + System.lineSeparator() + "FIELD3=" + System.lineSeparator()))
Вызываемый метод выглядит так:
public StreamingResponseBody streamReport(@PathVariable("type") @NotNull String type, @PathVariable("id") @NotNull Long id, ReportConfiguration config, HttpServletResponse response) throws Exception {
ReportServiceHandler handler = reportHandlerFactory.getHandler(type);
final String reportFilename = handler.getReportFileName(id, reportConfiguration);
response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + reportFilename);
response.setContentType("text/csv");
return new StreamingResponseBody() {
@Override
public void writeTo(OutputStream outputStream) throws IOException {
try {
response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + reportFilename);
response.setContentType("text/csv");
ServletOutputStream out = (ServletOutputStream) outputStream;
handler.generateReport(out, id, reportConfiguration);
out.flush();
} catch ( Exception e ) {
response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "inline");
response.setContentType("");
throw new IOException(e);
}
}
};
}
Отладка показывает, что исходный запрос содержит ответ от асинхронного внутри него, но объект асинхронного ответа (в пределах mvcResult1) не копируется во время asyncDispatch, поэтому и contextType, и строка содержимого равны нулю.
Есть ли здесь пропущенная тестовая конфигурация, которая обрабатывает async mvcResult, чтобы можно было утверждать содержимое?
1 ответ
Я довольно преуспел в этом. Вот что я делаю по-другому:
return new StreamingResponseBody() {
@Override
public void writeTo(OutputStream outputStream) throws IOException {
try {
... same
out.flush();
} catch ( Exception e ) {
... your error handling
} finally {
// Try to close the stream
try {
if (out != null) {
out.close();
}
} catch (Throwable t) {
// not much we can do
}
}
}
};
Теперь мои тесты выглядят так же, как и ваши. Читая ваш код, я не понимаю, почему вы дважды вызываете функцию execute(). Мне нужно только один раз.
//Same
final MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(wac)
.apply(SecurityMockMvcConfigurers.springSecurity())
.build();
// Same
MvcResult mvcResult1 = mockMvc.perform(
get(....))
.andExpect(status().isOk())
.andExpect(request().asyncStarted())
.andReturn();
mvcResult1.getAsyncResult();
// From this point on, I have complete response,
// if it's not bugging you to place the entire file in memory
String thisIsYourFileContent = mvcResult1.getResponse().getContentAsString();
// Go on asserting the content of the file...
В надежде, что это поможет кому-то.