I have a filter for logging some information for each request to a Spring Boot application. Some of this information I need to extract from the body. That's not a problem in itself, but to do so I use ContentCachingResponseWrapper
, and that is messing up my unit tests.
Here is a simplified version of my filter:
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();
}
}
And here is a simplified version of my test:
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));
}
The problem is that when running my tests, wrappedResponse.getContentAsByteArray()
returns an empty array.
There are 2 things wrong with your code
ContentCachingResponseWrapper
ContentCachingResponseWrapper
has no change of caching the response.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();
}
}
Now the response will be wrapped in the wrapper for responses written further down the FilterChain
. This is also something you can leverage in your testcase by mocking the FilterChain
and write the response in an answer.
void myTest() throws ServletException, IOException {
var body = "This is a body that my service might return.";
var req = new MockHttpServletRequest();
var res = new MockHttpServletResponse();
var mockChain = Mockito.mock(FilterChain.class);
Mockito.when(mockChain.doFilter(any(), any())
.thenAnswer((it -> {
var response = it.getArgument(1, HttpServletResponse.class);
response.getWriter().print(body);
response.getWriter().flush();
response.setContentLength(body.length());
return null;
});
myFilter.doFilterInternal(req, res, mockChain);
}
Something along these lines should do the trick.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.