使用ContentCachingResponseWrapper的签名Filter如何编写Mockito单元测试
问题根因
你在自定义Servlet的doPost方法中,没有使用方法入参传入的resp对象写入响应,而是直接写入了外部声明的原始MockHttpServletResponse res。
Filter执行chain.doFilter时传入的是自身包装好的ContentCachingResponseWrapper实例,也就是doPost方法的resp入参,你绕开包装实例直接写原始响应,ContentCachingResponseWrapper自然捕获不到任何内容。
修正后的测试代码
@ExtendWith(MockitoExtension.class) class ResponseSignerFilterTest { @Test void exampleTest() throws ServletException, IOException { final ResponseSignerFilter filter = new ResponseSignerFilter(appPrivateKey, getJwtSettings()); final MockHttpServletRequest req = new MockHttpServletRequest(); req.setMethod("POST"); final MockHttpServletResponse res = new MockHttpServletResponse(); res.setContentType("application/json"); final MockFilterChain filterChain = new MockFilterChain(new HttpServlet() { @Override protected void doPost(final HttpServletRequest req, final HttpServletResponse resp) throws IOException { // 必须使用入参的resp对象写入,这是Filter传入的包装实例 resp.getWriter().write("test-body"); // 也可以用流写入:resp.getOutputStream().write("test-body".getBytes(StandardCharsets.UTF_8)); } }); filter.doFilter(req, res, filterChain); // 执行断言逻辑,比如: String responseContent = res.getContentAsString(StandardCharsets.UTF_8); // 验证响应内容、签名头等 } }
额外注意点
- 不要在测试逻辑中主动调用
setCommitted(true),ContentCachingResponseWrapper需要在签名计算完成后才将缓存内容写回原始响应,提前标记响应为已提交会导致写回失败 - 不需要手动设置
contentLength,包装类会自动根据缓存的内容长度处理
内容的提问来源于stack exchange,提问作者BarbetNL
相关产品推荐
相关产品推荐

