为什么在Spring WebMvcTest中没有响应体?

4

我想测试当REST控制器返回错误请求时DefaultErrorAttributes的消息。控制器会抛出一个QueryException,由ControllerAdvice处理。

@ControllerAdvice
public class ErrorHandlingControllerAdvice {

   @ExceptionHandler(QueryException.class)
   void onApplicationException(QueryException e, HttpServletResponse response) throws IOException {
       response.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());
   }

}

响应内容:
{
   "timestamp": "2018-12-04T17:05:37.403+0000",
   "status": 400,
   "error": "Bad Request",
   "message": "Query error message",
   "path": "/search/v1/query/x"
}

WebMvcTest 测试会在上下文中加载 ControllerAdvice,可以正确处理异常(我用断点检查过)。但问题是响应的内容为空。断言 content().string("") 虽然通过了,但实际上不应该这样。

@SpringJUnitConfig({QueryResource.class, ErrorHandlingControllerAdvice.class})
@WebMvcTest(QueryResource.class)
public class QueryResourceTest {

   @Autowired
   private MockMvc mvc;

   @Test
   public void testQuery() throws Exception {
       String xmlQuery = ResourceHelper.loadResource("/rest/query.xml");
       this.mvc.perform(post("/v1/query/test")
               .contentType(MediaType.APPLICATION_XML)
               .content(xmlQuery))
               .andExpect(status().isBadRequest())
               .andExpect(content().string(""))
               .andExpect(jsonPath("$.message", is("Query error message")));
   }
}

如果收到了400错误请求,服务器会返回什么内容作为回应呢?换句话说,如果请求是400-Bad Request,那么服务器将发送什么内容? - Randy Casburn
预期的响应是由ControllerAdvice返回的DefaultErrorAttributes对象的JSON表示形式。 - Sydney
JSONPath也通过了吗? - Code_Is_Law
1个回答

3

这里有一条信息,我想测试......。您已经成功地完成了这项任务。因此,我相信问题是“为什么没有将响应发送回来,以便我可以阅读它?”

您正在做的事情是将单元测试的概念与希望像集成测试一样获取结果的愿望混淆在一起。

这种情况发生的明显原因与运行时环境和测试环境之间的区别有关。这是因为在运行时环境中,您有一个分派响应的servlet容器。在这里,MockMVC在没有使用servlet容器的情况下运行。这意味着没有机制可以将DefaultErrorAttributes分派并传递回作为响应。

这里是一个支持请求和详细说明为什么会出现这种情况:

MockMvc doesn't use spring-boot's mvc exception handler

该GitHub问题还指向了一个解决此问题的MockMVC SPR:

Actually support request forwarding in MockRequestDispatcher

要执行您构建的这种类型的集成测试,您需要启动Spring Boot应用程序上下文并启动服务器。为此,只需按以下方式重新包装您的测试类:

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class QueryResourceTest {
   // ...
}

使用@WebEnvironment设置的@SpringBootTest注释在这里用于启动服务器。当您更多地进入集成测试并远离使用MockMVC进行单元测试时,可能需要进行其他更改。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接