对此代码进行单元测试的最佳方法是什么?当条件为真时,我需要为httpResponse建立一致的检查sendError()。提前谢谢!
编辑:不幸的是,这个过滤器不适用于Spring MVC,因此我的选择有限。
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain filterchain) throws IOException, ServletException {
String ipAddress = request.getRemoteAddr();
if( SomeParameterCheckingFunction ((request)) ) {
logger.error("Error detected! Time: " + new Date().toString() + ", Originating IP: " + ipAddress);
if (response instanceof HttpServletResponse){
HttpServletResponse httpResponse = (HttpServletResponse) response;
httpResponse.sendError(HttpServletResponse.SC_FORBIDDEN,"You are not allowed to access the server!");
}
}
filterchain.doFilter(request, response);
}
答案 0 :(得分:4)
例如,当使用 Mockito 模拟框架时,提供的doFilter()
方法可以使用以下测试用例进行JUnit测试:
@Test
public void testDoFilter() throws IOException, ServletException {
// create the objects to be mocked
HttpServletRequest httpServletRequest = mock(HttpServletRequest.class);
HttpServletResponse httpServletResponse = mock(HttpServletResponse.class);
FilterChain filterChain = mock(FilterChain.class);
// mock the getRemoteAddr() response
when(httpServletRequest.getRemoteAddr()).thenReturn("198.252.206.16");
AccessFilter accessFilter = new AccessFilter();
accessFilter.doFilter(httpServletRequest, httpServletResponse,
filterChain);
// verify if a sendError() was performed with the expected values
verify(httpServletResponse).sendError(HttpServletResponse.SC_FORBIDDEN,
"You are not allowed to access the server!");
}
答案 1 :(得分:0)
一个选项可能是将SomeParameterCheckingFunction
的定义从过滤器本身中拉出(并在过滤器中使用它)。然后,您可以单独测试该逻辑。但是,我不确定这对你来说是否足够。
另一种选择可能是使用Mockito测试过滤器类。这将涉及一些劳动力,嘲笑请求,响应,过滤链,日志记录等。您应该能够在之后验证response.sendError()调用(假设静态导入Mockito。*方法):
//setup mock with concrete class for instanceof check
ServletResponse resp = mock(HttpServletResponse.class);
//define behavior for desired method with void return type. this appears optional for mocks.
//doNothing().when(resp).sendError(anyInt(), anyString());
//your test here, passing in resp
if(resp instanceof HttpServletResponse) resp.sendError(400, "blah");
//verify method was called
verify(resp).sendError(400, "blah");
可能有或没有办法用HttpUnit来测试您的过滤器,但这可能无法满足您对正确单元测试的需求。
答案 2 :(得分:0)
2018年2月更新:OpenBrace Limited has closed down,不再支持其ObMimic产品。
以下是一个示例,说明如何使用我的ObMimic容器外测试副本库为Servlet API测试“sendError”。
首先,关于给定的doFilter代码的一些注释:
“((请求))”大概只是“(请求)”。
“logger”的性质没有显示出来,所以我现在忽略了这一点并不相关。
给定的过滤器将检查非HTTP请求,但如果它们被拒绝,则会写入通常的日志消息,但会跳过sendError并执行正常处理。根据您要执行的操作,您可能希望预先拒绝非HTTP请求,或者根本不检查它们,或者执行其他类型的拒绝来代替“sendError”。现在我假设我们只对如何在HTTP请求上测试“sendError”感兴趣。
下面的示例测试表明,即使调用sendError,处理仍然会进入正常的“doFilter”调用。假设这不是故意的,“sendError”后面应该是“return”,或者“doFilter”应该是“else”子句。
对于以下示例代码:
我使用JUnit作为测试框架,但它也可以是TestNG或其他任何东西。
对于“SomeParameterCheckingFunction”,如果远程IP地址是“1.1.1.1”,我刚刚使用了一个返回true。
“sendError”生成一个显示给定消息的HTML响应。对于此示例,我只检查响应正文是否包含给定的消息。如果你想检查哪些参数值传递给“sendError”,ObMimic的“专业版”有一个“历史”功能,可以让你这样做。或者您可以在单独的响应实例上执行“sendError”,然后检查响应主体是否完全匹配。
无论如何,这是示例代码:
package com.openbrace.experiments.examplecode.stackoverflow13365536;
import static org.junit.Assert.*;
import com.openbrace.experiments.examplecode.stackoverflow13365536.YourFilter;
import com.openbrace.obmimic.mimic.servlet.FilterChainMimic;
import com.openbrace.obmimic.mimic.servlet.FilterConfigMimic;
import com.openbrace.obmimic.mimic.servlet.ServletMimic;
import com.openbrace.obmimic.mimic.servlet.http.HttpServletRequestMimic;
import com.openbrace.obmimic.mimic.servlet.http.HttpServletResponseMimic;
import com.openbrace.obmimic.support.servlet.EndPoint;
import org.hamcrest.CoreMatchers;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* Example tests for {@link YourFilter#doFilter(ServletRequest, ServletResponse,
* FilterChain)}.
*
* @author Mike Kaufman, OpenBrace Limited
*/
public class YourFilterTest {
/** The filter to be tested by this instance's test. */
private YourFilter filter;
/** The "mimic" request to be used in this instance's test. */
private HttpServletRequestMimic request;
/** The "mimic" response to be used in this instance's test. */
private HttpServletResponseMimic response;
/** The filter chain to be used in this instance's test. */
private FilterChainMimic filterChain;
/**
* Set up for this instance's test by creating an initialized filter and a
* request, response and filter chain for use in the test.
*
* @throws ServletException if the filter's init method throws such an
* exception.
*/
@Before
public void setUp() throws ServletException {
/*
* Note that for this example's simple filter and tests:
* - We don't need anything particular in the filter's FilterConfig.
* - We don't need any particular ServletContext, so we can leave
* ObMimic to use its default ServletContext throughout.
* - We don't need to retain any references to the filter's FilterConfig
* or ServletContext.
* - We can use a FilterChainMimic with default values as the filter
* chain. This has a ServletMimic as the next thing in the chain, and
* ServletMimic keeps a count of the calls to its service method, so
* we can use this to check whether the filter chain's doFilter has
* been invoked.
*/
filter = new YourFilter();
filter.init(new FilterConfigMimic());
request = new HttpServletRequestMimic();
response = new HttpServletResponseMimic();
filterChain = new FilterChainMimic();
}
/**
* Test the doFilter method with an example request for which
* SomeParameterCheckingFunction returns true (so that the FORBIDDEN
* response should result).
*
* @throws ServletException if the servlet throws such an exception.
* @throws IOException if the servlet throws such an exception.
*/
@Test
public void testYourFilterWithForbiddenRequest()
throws ServletException, IOException {
// Configure the request so that SomeParameterCheckingFunction will
// return true, which for purposes of this example is triggered by a
// particular "remote address".
request.getMimicState().setRemoteEndPoint(
new EndPoint(null, "1.1.1.1", null));
// Invoke the doFilter method.
filter.doFilter(request, response, filterChain);
// Check that the response is now FORBIDDEN, and that its HTML content
// does include the expected text message.
int responseCode = response.getMimicState().getHttpStatusCode();
String responseBody = response.getMimicState().getBodyContentAsString();
String expectedMessage = "You are not allowed to access the server!";
assertEquals("Response has incorrect status code",
HttpServletResponse.SC_FORBIDDEN, responseCode);
Assert.assertThat("FORBIDDEN response does not include expected message",
responseBody, CoreMatchers.containsString(expectedMessage));
// Check that the filter chain was not invoked. As we've used a
// FilterChainMimic with default values, its "target" is a ServletMimic,
// so we can just check if there have been any calls to that Servlet.
ServletMimic targetServlet
= (ServletMimic) filterChain.getMimicState().getTarget();
boolean filterChainInvoked
= targetServlet.getMimicState().getServiceCount() > 0;
assertFalse("FORBIDDEN response but filterChain.doFilter still called",
filterChainInvoked);
}
}
如果您想尝试一下,可以在ObMimic网站上找到ObMimic的完整详情和免费下载。