简体   繁体   中英

How do I unit test a Servlet Filter with jUnit?

Implemented doFilter() . How to properly cover Filter with jUnit ?

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 and FilterChain are all interfaces, so you can easily create test stubs for them, either by hand or using a mocking framework.

Make the mock objects configurable so that you can prepare a canned response to getRequestURI() and so that you can query the ServletResponse to assert that sendRedirect has been invoked.

Inject a mock ModeService.

Invoke doFilter passing the mock ServletRequest, ServletResponse and FilterChain as its parameters.

@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());
}

In practice you'll want to move the setup into an @Before setUp() method, and write more @Test methods to cover every possible execution path.

... and you'd probably use a mocking framework like JMock or Mockito to create mocks, rather than the hypothetical MockModeService etc. I've used here.

This is a unit testing approach, as opposed to an integration test. You are only exercising the unit under test (and the test code).

You could use a mocking framework in order to mock the above HttpServletRequest , HttpServletResponse and FilterChain objects and their behavior. Depending on the framework, you have certain functionality in order to verify if during the execution of the code correct actions on the mocked objects where taken.

For example when using the Mockito mock framework, the provided doFilter() method could be JUnit tested using below test case:

@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");
}

If you are using Spring then it has own mocks:

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

For example, you can add headers and set test Uri.

So your test can be smth like this:

@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());
    }
}

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM