如何为返回PDF文件的spring启动测试用例设置内容类型

如何为返回PDF文件的spring启动测试用例设置内容类型,spring,spring-boot,junit,testcase,spring-boot-test,Spring,Spring Boot,Junit,Testcase,Spring Boot Test,我目前正在使用Spring boot test测试我的一个服务。该服务导出所有用户数据,并在成功完成后生成CSV或PDF。在浏览器中下载文件 下面是我在测试类中编写的代码 MvcResult result = MockMvc.perform(post("/api/user-accounts/export").param("query","id=='123'") .contentType(MediaType.APPLICATION_JSON_VALUE) .accept(Med

我目前正在使用Spring boot test测试我的一个服务。该服务导出所有用户数据,并在成功完成后生成CSV或PDF。在浏览器中下载文件

下面是我在测试类中编写的代码

MvcResult result =   MockMvc.perform(post("/api/user-accounts/export").param("query","id=='123'")
    .contentType(MediaType.APPLICATION_JSON_VALUE)
    .accept(MediaType.APPLICATION_PDF_VALUE)
    .content(TestUtil.convertObjectToJsonBytes(userObjectDTO)))
    .andExpect(status().isOk())
    .andExpect(content().contentType(MediaType.APPLICATION_PDF_VALUE))
    .andReturn();
String content = result.getResponse().getContentAsString();  // verify the response string.
下面是我的资源类代码调用来到这个地方-

    @PostMapping("/user-accounts/export")
@Timed
public ResponseEntity<byte[]> exportAllUsers(@RequestParam Optional<String> query, @ApiParam Pageable pageable, 
@RequestBody UserObjectDTO userObjectDTO) {
HttpHeaders headers = new HttpHeaders();
.
.
.

 return new ResponseEntity<>(outputContents, headers, HttpStatus.OK);

 }

我想知道,我应该如何检查我的反应。还有,响应所需的内容类型。

406意味着您的客户机要求的内容类型可能是服务器认为无法提供的pdf

我猜调试时代码正常工作的原因是rest客户端没有像测试代码那样添加请求pdf的ACCEPT头


要解决此问题,请将@PostMapping annotation products=MediaType.APPLICATION\u PDF\u值添加到您的@PostMapping annotation products=MediaType.APPLICATION\u PDF\u值中。请参见

您在其他地方遇到问题。如application/problem+json内容类型所述,似乎发生了异常/错误。这可能是在异常处理程序中设置的。因为您的客户只希望返回application/pdf 406

您可以添加一个测试用例来读取错误详细信息,以了解错误到底是什么

差不多

MvcResult result = MockMvc.perform(post("/api/user-accounts/export").param("query","id=='123'")
    .contentType(MediaType.APPLICATION_JSON_VALUE)
    .accept(MediaType.APPLICATION_PROBLEM_JSON_VALUE)
    .content(TestUtil.convertObjectToJsonBytes(userObjectDTO)))
    .andExpect(status().isOk())
    .andExpect(content().contentType(MediaType.APPLICATION_PROBLEM_JSON_VALUE))
    .andReturn();
String content = result.getResponse().getContentAsString();  // This should show you what the error is and you can adjust your code accordingly. 
接下来,如果您预期会出现错误,可以将accept类型更改为同时包含pdf和问题json类型

注意-此行为取决于您拥有的SpringWebMVC版本


最新的SpringMVC版本考虑了响应实体中设置的content-type头,忽略了accept头中提供的内容,并将响应解析为可能的格式。因此,您进行的相同测试不会返回406代码,而是返回应用程序json问题内容类型的内容

我在@veeram的帮助下找到了答案,并逐渐了解到我的MappingJackson2HttpMessageConverter配置不符合我的要求。我覆盖了它默认支持的Mediatype,它解决了这个问题

默认支持-

implication/json
application*/json
更改代码以修复此情况-

@Autowired
private MappingJackson2HttpMessageConverter jacksonMessageConverter;

List<MediaType> mediaTypes = new ArrayList<>();
mediaTypes.add(MediaType.ALL);
jacksonMessageConverter.setSupportedMediaTypes(mediaTypes);

正如我在聊天中告诉你的:一个小时是堆栈溢出的短时间。如果你想尽快得到回复,请雇佣一名开发人员。我编辑了你的文章,至少有一个恰当的问题陈述。继续堆栈溢出的方法是等待问题通过审阅队列,而不是滥用系统并简单地删除和重新设置它。请务必考虑到这里的每个人都是志愿者,而且都是平等的。你没有资格在几分钟内得到答复,这取决于回答者。是的,你更新了前面的问题,我急切地想得到答案。我知道一个小时的时间已经不多了。但有时我们确实会不顾一切地完成工作。所以它造成了这场混乱,正如我三次告诉你的,这与我们无关。你问了一个问题,人们可能会也可能不会自愿花时间来帮助你。滥用系统,尽可能多地滥发你的问题,徒劳地希望得到答案,这是不能容忍的。你只需坐下来等待回答。更好的问题会更快得到答案,所以试着从语言、代码、示例、错误等各个方面改进你的问题,如果两天后你仍然没有收到答案,你可以悬赏。如果失败了,那就是这样了。我明白你的意思了。我不认为你的测试用例缺少任何东西,我认为这是spring或其他库中我们看不到的异常或错误。尝试调试产生应用程序/问题json媒体类型的spring源代码。建立一个GitHub项目是值得的。您是否使用任何问题详细信息模块(通常会生成问题json媒体类型)?您好,JacobSTL,我做了必要的更改,但收到以下错误java.lang.AssertionError:Content type Expected:application/pdf Actual:application/problem+json。我相信我们没有使用任何特定的产品类型,因为我们使用此服务下载PDF和CSV类型的文件。如果您希望根据接收到的ACCEPT标头发送不同的内容类型,那么您需要单独的控制器方法,按标头拆分,请参阅我尝试了以下资源的方法定义,`@PostMappingvalue=/user accounts/export,consumes=MediaType.APPLICATION\u JSON\u VALUE,products={MediaType.APPLICATION\u PDF\u VALUE,text/csv}`但仍然得到http错误代码406。我想验证响应类型为'application/pdf',但涉及到application/problem+js。如果您在备注中提到,返回将取决于您的spring web mvc,请您指向一个文档引用。在这种情况下,我们如何实际测试。我想将最终结果内容类型与application/pdfHI@veeram进行比较,我遵循了上述方法,并发现了406错误,其中包含更详细的正文,即{type:http://abc-aaa/problem/problem-with-message,标题:不可接受,状态:40
6,详细信息:找不到可接受的表示,路径:/api/用户帐户/导出,消息:error.http.406}查看github。最终结果内容类型不是application/pdf。这就是问题所在。您如何设置内容类型。它是响应实体标题的一部分吗?根据5.0.5,如果在标题中设置内容类型并且没有生成注释,则不应出现406错误。标题在我们的服务中以以下方式手动设置:headers.setContentTypeMediaType.parseMediaTypeapplication/pdf;headers.setContentDispositionFormDatafileName,文件名;headers.setCacheControlmust-revalidate,后检查=0,预检查=0;然后以下面的方式返回新的ResponseEntityPutContents、Header、HttpStatus.OK;。通常我们在浏览器中获得下载文件。但在测试用例执行中,它从HTTP.200转换为406,从application/pdf转换为application/problem+jsonhello-Veeram,正如我调试spring代码时所建议的那样。并且知道Mapping2JacksonHttpMessageConverter具有默认支持值,即application/json和application*\json。我覆盖了这些属性,它解决了问题。谢谢你的帮助。
@Autowired
private MappingJackson2HttpMessageConverter jacksonMessageConverter;

List<MediaType> mediaTypes = new ArrayList<>();
mediaTypes.add(MediaType.ALL);
jacksonMessageConverter.setSupportedMediaTypes(mediaTypes);