使用MockMvc测试Spring下载链接时出现“找不到可接受的表示形式”

时间:2019-01-28 11:15:49

标签: spring spring-mvc

我有一个控制器,应允许下载具有任意内容类型的文件:

@GetMapping(value="/download/{directory}/{name}",
            consumes=MediaType.ALL_VALUE)
@Timed
public ResponseEntity<byte[]> downloadFile(@PathVariable String directory,
                                           @PathVariable String name) {
    log.debug("REST request to download File : {}/{}", directory, name);

    byte[] content = "it works".getBytes();
    HttpHeaders headers = new HttpHeaders();
    headers.add(HttpHeaders.CONTENT_TYPE, "text/plain");
    return new ResponseEntity<>(content, headers, HttpStatus.OK);
}

我想在这样的单元测试中进行测试:

...
private MockMvc restFileMockMvc;

@Before
public void setup() {
    MockitoAnnotations.initMocks(this);

    final FileResource fileResource = new FileResource(fileService);
    this.restFileMockMvc = MockMvcBuilders.standaloneSetup(fileResource)
        .setCustomArgumentResolvers(pageableArgumentResolver)
        .setControllerAdvice(exceptionTranslator)
        .setConversionService(createFormattingConversionService())
        .setMessageConverters(jacksonMessageConverter)
        .setValidator(validator).build();
}

@Test
@Transactional
public void downloadFile() throws Exception {
    String url = "/api/download/it/works.txt";
    restFileMockMvc.perform(get(url).header(HttpHeaders.ACCEPT, "*/*"))
                   .andDo(MockMvcResultHandlers.print()) // Debugging only!
                   .andExpect(status().isOk());
}

但是,显然,内容类型存在问题。接受标头。 MockMvcResultHandlers.print()产生以下结果:

MockHttpServletRequest:
      HTTP Method = GET
      Request URI = /api/download/DIRDIR/NAMENAME
       Parameters = {}
          Headers = {Accept=[*/*]}
             Body = <no character encoding set>
    Session Attrs = {}

Handler:
             Type = com.example.storage.web.rest.FileResource
           Method = public org.springframework.http.ResponseEntity<byte[]> com.example.storage.web.rest.FileResource.downloadFile(java.lang.String,java.lang.String)

Async:
    Async started = false
     Async result = null

Resolved Exception:
             Type = org.springframework.web.HttpMediaTypeNotAcceptableException

ModelAndView:
        View name = null
             View = null
            Model = null

FlashMap:
       Attributes = null

MockHttpServletResponse:
           Status = 406
    Error message = null
          Headers = {Content-Type=[application/problem+json]}
     Content type = application/problem+json
             Body = {"type":"https://www.jhipster.tech/problem/problem-with-message","title":"Not Acceptable","status":406,"detail":"Could not find acceptable representation","path":"/api/download/DIRDIR/NAMENAME","message":"error.http.406"}
    Forwarded URL = null
   Redirected URL = null
          Cookies = []

看起来请求是与Accept: */*发送在一起的。 Spring会抱怨什么?

2 个答案:

答案 0 :(得分:1)

在测试用例中使用的消息转换器可能是一个问题。我也面临类似的问题,并通过在我的MockMvc的messageConverter中传递其他参数来解决了该问题

 this.restMockMvc = MockMvcBuilders.standaloneSetup(testResource)
        .setCustomArgumentResolvers(pageableArgumentResolver)
        .setControllerAdvice(exceptionTranslator)
        .setMessageConverters(jacksonMessageConverter,new 
       ByteArrayHttpMessageConverter()).build();

您需要为MockMVC重载消息转换器属性。有关更多信息,relevant question

答案 1 :(得分:0)

我已经在使用@SpringJUnitWebConfig(...),并且在导入的Config中包含了@EnableWebMvc注释。这似乎添加了所有必需的转换器。例如

@SpringJUnitWebConfig(MyTestConfig.class)
class MyTest {

  @Inject
  private WebApplicationContext wac;

  private MockMvc mockMvc;
  ...
}

@EnableWebMvc
class MyTestConfig {
  @Bean
  ...
}