Как сделать unit test сервлет-фильтр с помощью jUnit? - программирование

Как сделать unit test сервлет-фильтр с помощью jUnit?

Реализовано doFilter(). Как правильно накрыть фильтр с помощью 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);
}
4b9b3361

Ответ 1

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 и т.д. Я использовал здесь.

Это метод модульного тестирования, а не интеграционный тест. Вы выполняете только тестируемое устройство (и тестовый код).

Ответ 2

Вы можете использовать фальшивую фреймворк, чтобы издеваться над объектами HttpServletRequest, HttpServletResponse и FilterChain и их поведением. В зависимости от структуры у вас есть определенная функциональность, чтобы проверить, выполняются ли во время выполнения кода правильные действия над издеваемыми объектами.

Например, при использовании фреймворка 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");
}

Ответ 3

Если вы используете Spring, то у него есть собственные mocks:

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