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...

В надежде, что это поможет кому-то.

Другие вопросы по тегам