如何为 spring 引导测试用例设置内容类型 returns PDF 文件

How to set content-type for a spring boot test case which returns PDF file

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

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

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.

下面是我的资源class代码(调用到这里)-

    @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);

 }

当我调试我的服务并在退出之前进行调试时,我得到的内容类型为 'application/pdf' 和状态为 200.I 已尝试在我的测试用例中复制相同的内容类型。不知何故,它在执行过程中总是抛出以下错误 -

   java.lang.AssertionError: Status 
   Expected :200
   Actual   :406

我想知道,我应该如何检查我的响应 (ResponseEntity)。另外,响应所需的内容类型应该是什么。

406 表示您的客户端正在请求服务器认为它无法提供的内容类型(可能是 pdf)。

我猜你的代码在调试时工作的原因是你的休息客户端没有像测试代码那样添加要求 pdf 的 ACCEPT header。

要解决此问题,请添加到您的 @PostMapping 注释 produces = MediaType.APPLICATION_PDF_VALUE 请参阅 https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/bind/annotation/PostMapping.html#produces--

你在其他地方有问题。似乎 exception/error 发生了 application/problem+json 内容类型。这可能是在异常处理程序中设置的。因为您的客户只期望 application/pdf 406 是 returned。

您可以添加测试用例来读取错误详细信息以了解具体错误是什么。

类似于

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. 

如果您预计会出现错误,您可以更改接受类型以同时包含 pdf 和问题 json 类型。

注意 - 此行为取决于您拥有的 spring web mvc 版本。

最新的springmvc版本考虑了响应实体中设置的内容类型header而忽略了接受header中提供的内容并解析了响应格式可能.因此,您进行的相同测试不会 return 406 代码,而是 return 具有应用程序 json 问题内容类型的内容。

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

默认支持 -

implication/json
application*/json

已完成代码更改以解决此问题 -

@Autowired
private MappingJackson2HttpMessageConverter jacksonMessageConverter;

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