如何使用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); }
ServletRequest
, ServletResponse
和FilterChain
都是接口,因此您可以手动或使用模拟框架轻松地为它们创建测试存根。
使模拟对象可配置,以便您可以准备对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方法,而不是集成测试。 您只是在运行被测单元(和测试代码)。
您可以使用模拟框架来模拟上面的HttpServletRequest
, HttpServletResponse
和FilterChain
对象及其行为。 根据框架的不同,您可以使用某些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()); } }