Mocked HttpServletResponse的getContentType()返回null问题排查
解决Servlet单元测试中Mockito模拟HttpServletResponse时getContentType()返回null的问题
兄弟,这个坑我踩过!你遇到的问题本质是Mockito默认的模拟对象不会自动跟踪方法调用后的状态变化:当你调用response.setContentType("text/plain")时,默认的HttpServletResponse mock对象根本不会把这个值存下来,所以后续调用getContentType()自然返回null;而你的StringWriter验证正常,是因为你应该是手动替换了response的Writer输出流,那部分是单独捕获的,和contentType的状态跟踪逻辑不相关。
下面给你两种常用的解决方法:
方法一:用Mockito的doAnswer跟踪set方法的参数,绑定get方法的返回
这种方法适合纯Mockito环境,手动让mock对象记住setContentType设置的值:
// 定义变量保存contentType的值 String capturedContentType = null; // 创建HttpServletResponse的mock对象 HttpServletResponse response = Mockito.mock(HttpServletResponse.class); // 让setContentType调用时,把传入的参数存到变量里 Mockito.doAnswer(invocation -> { capturedContentType = invocation.getArgument(0); return null; }).when(response).setContentType(Mockito.anyString()); // 指定getContentType返回我们捕获到的值 Mockito.when(response.getContentType()).thenAnswer(invocation -> capturedContentType); // 执行Servlet的目标方法(比如doGet/doPost) yourServlet.doGet(request, response); // 现在断言就能正常通过了 assertEquals("text/plain", response.getContentType());
方法二:使用带状态跟踪的Response包装类(或Spring的MockHttpServletResponse)
如果是Spring项目,直接用Spring提供的MockHttpServletResponse最省心,它本身就会自动跟踪所有Servlet响应的状态参数:
// 创建Spring自带的MockHttpServletResponse,自带状态跟踪 MockHttpServletResponse response = new MockHttpServletResponse(); // 执行Servlet方法 yourServlet.doGet(request, response); // 直接断言即可 assertEquals("text/plain", response.getContentType());
如果是纯Servlet环境,也可以自己写个简单的包装类来跟踪contentType:
// 自定义Response包装类,跟踪contentType class TrackingResponseWrapper extends HttpServletResponseWrapper { private String contentType; public TrackingResponseWrapper(HttpServletResponse response) { super(response); } @Override public void setContentType(String type) { this.contentType = type; super.setContentType(type); } @Override public String getContentType() { return contentType != null ? contentType : super.getContentType(); } } // 使用方式 HttpServletResponse mockResponse = Mockito.mock(HttpServletResponse.class); TrackingResponseWrapper response = new TrackingResponseWrapper(mockResponse); yourServlet.doGet(request, response); assertEquals("text/plain", response.getContentType());
核心思路就是:默认的Mockito mock对象是"无状态"的,不会帮你保存set方法设置的属性,必须手动给它添加状态跟踪的逻辑,或者使用本身就支持状态跟踪的模拟实现。
内容的提问来源于stack exchange,提问作者1nfinity
相关产品推荐
相关产品推荐

