我正在尝试为我编写的过滤器编写单元测试。这听起来很简单,但有一点我无法弄清楚哪个是设置ServletResponse的状态代码。不幸的是,这很复杂,因为我正在使用HttpServletResponseWrapper,因为我需要检查响应状态代码(因为我需要覆盖它并返回200)。作为参考,我得到一个IncludedResponse,它有一个getStatusCode(),但由于某种原因在JDK源中它返回0?!?无论如何,这是我所拥有的过滤器的一部分:
private void handleUploadFilePost(ServletResponse servletResponse, HttpServletResponse httpServletResponse,
HttpServletRequest httpServletRequest, FilterChain filterChain) throws IOException, ServletException {
RequestWrapper requestWrapper = new RequestWrapper(httpServletRequest);
ResponseWrapper responseWrapper = new ResponseWrapper(httpServletResponse);
String requestBodyTrimmed = getRequestBody(requestWrapper.getInputStream());
Case caseDetails = requestBodyMappingHelper.mapRequestBody(requestBodyTrimmed, Case.class);
filterChain.doFilter(requestWrapper, responseWrapper);
if (responseWrapper.getStatus() >= 400 && responseWrapper.getStatus() <= 599) {
...
}
}
不幸的是,这会在测试时产生问题。如果它是一个简单的ServletResponse我嘲笑它并做...
when(myServletResponse).getStatus().thenReturn(...)
但是,因为我正在为状态创建自定义包装器,所以它似乎无法设置此局部变量的状态代码,因为它在包装器中保存为int,它覆盖了HttpServletResponse setStatus。
因此,我可以使用Mockito或Powermock做我想做的事吗?设置HttpServletResponse值后,它会覆盖它并将状态存储在我的包装器中,但我无法使其工作。我已经尝试了以下内容:
doAnswer(new Answer() {
public Object answer(InvocationOnMock invocation) {
servletResponse.setStatus(400);
return null; // void method, so return null
}
}).when(filterChain).doFilter(Mockito.any(ServletRequest.class), Mockito.any(ServletResponse.class));
但由于某些原因,这不起作用。测试中的ServletResponse没有被模拟,我实际上正在创建它,以便触发它的setStatus(),它将被Wrapper截获;
private IncludedResponse servletResponse;
servletResponse = new IncludedResponse();
servletResponse.setProxiedHttpServletResponse(new IncludedResponse());
非常感谢您提供的任何帮助。
非常感谢
答案 0 :(得分:1)
当(myServletResponse).getStatus()。thenReturn(...)
正确的是
当(myServletResponse.getStatus()的)强> .thenReturn(...)
或更改为更一般的形式:
doReturn(...).when(myServletResponse).getStatus()
还允许对void方法进行trowing异常:
doThrow(new *Exception())when(mock).veoidMethod();
我也不能这样做(doReturn)部分,因为我如何将包装器模拟为局部变量。这就是我需要设置原始ServletResponse.setStatus方法
的原因
如果要应用依赖注入,则可以轻松使用本地模拟。
答案 1 :(得分:0)
不知道为什么我之前没想过这个。我能做的是创建我自己的过滤器链:
FilterChain filterChain = new FilterChain() {
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse)
throws IOException, ServletException {
if (servletResponse instanceof HttpServletResponse) {
((HttpServletResponse) servletResponse).setStatus(400);
}
}
};
这样当响应回来时,我不需要模拟它或其他任何东西,但我实际上得到了包装器使用的响应对象。比尝试使用模拟更容易(如果有可能的话)。
感谢蒂莫西的评论。我会留下这个,以防其他人像我一样有脑块!