MockMvc 与端到端测试

MockMvc 是基于 spring-test 模块中的 Servlet API 模拟实现构建的,不依赖于正在运行的容器。因此,与使用实际客户端和正在运行的实时服务器进行的完整的端到端集成测试相比,存在一些差异。

最简单的理解方式是从一个空白的 MockHttpServletRequest 开始。你添加到其中的任何内容都将成为请求。可能会让你感到意外的是,默认情况下没有上下文路径;没有 jsessionid cookie;没有转发、错误或异步调度;因此,没有实际的 JSP 渲染。相反,“转发”和“重定向”的 URL 将保存在 MockHttpServletResponse 中,并且可以通过期望进行断言。

这意味着,如果你使用 JSP,你可以验证请求被转发到的 JSP 页面,但不会渲染任何 HTML。换句话说,JSP 不会被调用。但是请注意,所有其他不依赖于转发的渲染技术,例如 Thymeleaf 和 Freemarker,都会按预期将 HTML 渲染到响应主体。对于通过 @ResponseBody 方法渲染 JSON、XML 和其他格式也是如此。

或者,您可以考虑使用 Spring Boot 的 @SpringBootTest 进行完整的端到端集成测试支持。请参阅 Spring Boot 参考指南

每种方法都有其优缺点。Spring MVC Test 中提供的选项是经典单元测试到完整集成测试之间不同程度的测试。当然,Spring MVC Test 中的任何选项都不属于经典单元测试的范畴,但它们更接近于经典单元测试。例如,您可以通过将模拟服务注入控制器来隔离 Web 层,在这种情况下,您只通过 DispatcherServlet 测试 Web 层,但使用实际的 Spring 配置,就像您可能在隔离数据访问层的情况下测试数据访问层一样。此外,您可以使用独立的设置,一次专注于一个控制器,并手动提供使其正常工作的必要配置。

使用 Spring MVC Test 时另一个重要的区别是,从概念上讲,这样的测试是服务器端的,因此您可以检查使用了哪个处理程序、是否使用 HandlerExceptionResolver 处理了异常、模型的内容是什么、存在哪些绑定错误以及其他细节。这意味着更容易编写期望,因为服务器不是一个不透明的盒子,就像通过实际的 HTTP 客户端测试它时那样。这通常是经典单元测试的优势:它更容易编写、推理和调试,但不能替代完整的集成测试。同时,重要的是不要忽视这样一个事实,即响应是最重要的检查内容。简而言之,即使在同一个项目中,也存在多种测试风格和策略的空间。