Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I unit test a Servlet Filter with jUnit?

Tags:

java

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);
}
like image 598
Pilot Avatar asked Jul 12 '12 12:07

Pilot


People also ask

How do you test spring boot filters?

Just create an instance of the filter, use the mock classes and check the result. You are making all your tests for this filter overly complex.

Is it possible to group the test cases in JUnit?

JUnit test suites help to grouping and executing tests in bulk. Executing tests separately for all test classes is not desired in most cases. Test suites help in achieving this grouping. In JUnit, test suites can be created and executed with these annotations.


3 Answers

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).

like image 159
slim Avatar answered Oct 09 '22 03:10

slim


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");
}
like image 38
CodeNotFound Avatar answered Oct 09 '22 04:10

CodeNotFound


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());
    }
}
like image 24
Evgeny Konurbaev Avatar answered Oct 09 '22 04:10

Evgeny Konurbaev