【发布时间】:2021-12-17 01:38:48
【问题描述】:
我有一个过滤器,用于记录对 Spring Boot 应用程序的每个请求的一些信息。我需要从身体中提取其中一些信息。这本身不是问题,但为此我使用ContentCachingResponseWrapper,这会搞乱我的单元测试。
这是我的过滤器的简化版本:
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
try {
var wrappedResponse = response instanceof ContentCachingResponseWrapper ? (ContentCachingResponseWrapper) response : new ContentCachingResponseWrapper(response);
filterChain.doFilter(request, wrappedResponse);
} finally {
System.out.println("Response body: " + new String(wrappedResponse.getContentAsByteArray()));
wrappedResponse.copyBodyToResponse();
}
}
这是我的测试的简化版本:
void myTest() throws ServletException, IOException {
final String body = "This is a body that my service might return.";
var testResp = new MockHttpServletResponse();
testResp.getWriter().print(body);
testResp.getWriter().flush();
testResp.setContentLength(body.length());
myFilter.doFilterInternal(Mockito.mock(HttpServletRequest.class), testResp, Mockito.mock(FilterChain.class));
}
问题是在运行我的测试时,wrappedResponse.getContentAsByteArray() 返回一个空数组。
【问题讨论】:
-
为什么要这样做?响应没有被包装,至少你的过滤器没有包装任何东西。所以不确定你认为它是如何工作的。
-
@M.Deinum finally 块中的第一行不是将响应包装在 ContentCachingResponseWrapper 中吗?
-
不,它检查它是否是该类的实例并在事后包装。响应应在调用
filterchain.doFilter之前包装并作为响应传递。然后应在finally块中使用包装的响应。 -
谢谢。我可能在调试时移动了一些东西,因为这在之前(不测试时)有效。我现在已经更改了它,并且在测试期间行为仍然相同。
-
这也是意料之中的。当您在
ContentCachingResponseWrapper有时间拦截并缓存它之前编写响应时。
标签: java spring-boot unit-testing junit servlet-filters