如何使用jUnit对Servletfilter进行unit testing?

实现了doFilter() 。 如何用jUnit正确覆盖filter?

 public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws java.io.IOException, javax.servlet.ServletException { HttpServletRequest request = (HttpServletRequest) servletRequest; HttpServletResponse response = (HttpServletResponse) servletResponse; String currentURL = request.getRequestURI(); if (!currentURL.equals("/maintenance.jsp") && modeService.getOnline()) { response.sendRedirect("/maintenance.jsp"); } filterChain.doFilter(servletRequest, servletResponse); } 

ServletRequestServletResponseFilterChain都是接口,因此您可以手动或使用模拟框架轻松地为它们创建测试存根。

使模拟对象可配置,以便您可以准备对getRequestURI()的预设响应,以便您可以查询ServletResponse以断言已调用sendRedirect。

注入模拟ModeService。

调用doFilter,将模拟ServletRequest,ServletResponse和FilterChain作为参数传递。

 @Test public void testSomethingAboutDoFilter() { MyFilter filterUnderTest = new MyFilter(); filterUnderTest.setModeService(new MockModeService(ModeService.ONLINE)); MockFilterChain mockChain = new MockFilterChain(); MockServletRequest req = new MockServletRequest("/maintenance.jsp"); MockServletResponse rsp = new MockServletResponse(); filterUnderTest.doFilter(req, rsp, mockChain); assertEquals("/maintenance.jsp",rsp.getLastRedirect()); } 

在实践中,您需要将设置移动到@Before setUp()方法,并编写更多@Test方法以涵盖每个可能的执行路径。

…你可能会使用像JMock或Mockito这样的模拟框架来创建模拟,而不是假设的MockModeService等。我在这里使用过。

这是一种unit testing方法,而不是集成测试。 您只是在运行被测单元(和测试代码)。

您可以使用模拟框架来模拟上面的HttpServletRequestHttpServletResponseFilterChain对象及其行为。 根据框架的不同,您可以使用某些function来validation在执行代码期间是否对模拟对象执行了正确的操作。

例如,当使用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 getRequestURI() response when(httpServletRequest.getRequestURI()).thenReturn("/otherurl.jsp"); MaintenanceFilter maintenanceFilter = new MaintenanceFilter(); maintenanceFilter.doFilter(httpServletRequest, httpServletResponse, filterChain); // verify if a sendRedirect() was performed with the expected value verify(httpServletResponse).sendRedirect("/maintenance.jsp"); } 

如果您使用Spring,那么它有自己的模拟:

  • org.springframework.mock.web.MockFilterChain
  • org.springframework.mock.web.MockHttpServletRequest
  • org.springframework.mock.web.MockHttpServletResponse

例如,您可以添加标题并设置测试Uri。

所以你的测试可以像这样:

 @RunWith(MockitoJUnitRunner.class) public class TokenAuthenticationFilterTest { private static final String token = "260bce87-6be9-4897-add7-b3b675952538"; private static final String testUri = "/testUri"; @Mock private SecurityService securityService; @InjectMocks private TokenAuthenticationFilter tokenAuthenticationFilter = new TokenAuthenticationFilter(); @Test public void testDoFilterInternalPositiveScenarioWhenTokenIsInHeader() throws ServletException, IOException { MockHttpServletRequest request = new MockHttpServletRequest(); request.addHeader(TOKEN, token); request.setRequestURI(testUri); MockHttpServletResponse response = new MockHttpServletResponse(); MockFilterChain filterChain = new MockFilterChain(); when(securityService.doesExistToken(token)).thenReturn(true); tokenAuthenticationFilter.doFilterInternal(request, response, filterChain); assertThat(response.getStatus()).isEqualTo(HttpStatus.OK.value()); } }