How do I unit test a Servlet Filter with jUnit? ServletRequest, ServletResponse, FilterChain

huangapple go评论126阅读模式
英文:

How do I unit test a Servlet Filter with jUnit? ServletRequest, ServletResponse, FilterChain

问题

  1. @SlingFilter(order = -700, scope = SlingFilterScope.REQUEST)
  2. public class LoggingFilter implements Filter {
  3. private final Logger logger = LoggerFactory.getLogger(getClass());
  4. @Override
  5. public void doFilter(final ServletRequest request, final ServletResponse response,
  6. final FilterChain filterChain) throws IOException, ServletException {
  7. final SlingHttpServletRequest slingRequest = (SlingHttpServletRequest) request;
  8. logger.debug("request for {}, with selector {}", slingRequest
  9. .getRequestPathInfo().getResourcePath(), slingRequest
  10. .getRequestPathInfo().getSelectorString());
  11. filterChain.doFilter(request, response);
  12. }
  13. @Override
  14. public void init(FilterConfig filterConfig) {}
  15. @Override
  16. public void destroy() {}
  17. }
英文:

How to properly cover Filter with JUnit?

  1. @SlingFilter(order = -700, scope = SlingFilterScope.REQUEST)
  2. public class LoggingFilter implements Filter {
  3. private final Logger logger = LoggerFactory.getLogger(getClass());
  4. @Override
  5. public void doFilter(final ServletRequest request, final ServletResponse response,
  6. final FilterChain filterChain) throws IOException, ServletException {
  7. final SlingHttpServletRequest slingRequest = (SlingHttpServletRequest) request;
  8. logger.debug("request for {}, with selector {}", slingRequest
  9. .getRequestPathInfo().getResourcePath(), slingRequest
  10. .getRequestPathInfo().getSelectorString());
  11. filterChain.doFilter(request, response);
  12. }
  13. @Override
  14. public void init(FilterConfig filterConfig) {}
  15. @Override
  16. public void destroy() {}
  17. }

答案1

得分: 4

  1. @ExtendWith(MockitoExtension.class)
  2. public class LoggingFilterTest {
  3. @InjectMocks
  4. private LoggingFilter loggingFilter;
  5. @Mock
  6. private ServletRequest request;
  7. @Mock
  8. private ServletResponse response;
  9. @Mock
  10. private FilterChain filterChain;
  11. @Mock
  12. private RequestPathInfo requestPathInfo;
  13. @Test
  14. public void testDoFilter() throws IOException, ServletException {
  15. Mockito.when(request.getResourcePath()).thenReturn(requestPathInfo);
  16. Mockito.when(requestPathInfo.getResourcePath()).thenReturn("/testPath", "selectorString");
  17. Mockito.doNothing().when(filterChain).doFilter(Mockito.eq(request), Mockito.eq(response));
  18. loggingFilter.doFilter(request, response, filterChain);
  19. Mockito.verify(filterChain, times(1)).doFilter(Mockito.eq(request), Mockito.eq(response));
  20. }
  21. }

If you are using junit4, then change @ExtendWith(MockitoExtension.class) to @RunWith(MockitoJUnitRunner.class).

  1. <details>
  2. <summary>英文:</summary>
  3. You can use below code for your testing with `Junit-5`

@ExtendWith(MockitoExtension.class)
public class LoggingFilterTest{

  1. @InjectMocks
  2. private LoggingFilter loggingFilter;
  3. @Mock
  4. private ServletRequest request
  5. @Mock
  6. private ServletResponse response
  7. @Mock
  8. private FilterChain filterChain
  9. @Mock
  10. private RequestPathInfo requestPathInfo;
  11. @Test
  12. public void testDoFilter() throws IOException, ServletException{
  13. Mockito.when(request.getResourcePath()).thenReturn(requestPathInfo);
  14. Mockito.when(requestPathInfo.getResourcePath()).thenReturn(&quot;/testPath&quot;, &quot;selectorString&quot;);
  15. Mockito.doNothing().when(filterChain).doFilter(Mockito.eq(request), Mockito.eq(response));
  16. loggingFilter.doFilter(request, response, filterChain);
  17. Mockito.verify(filterChain, times(1)).doFilter(Mockito.eq(request), Mockito.eq(response));
  18. }

}

  1. If you are using `junit4` then change `@ExtendWith(MockitoExtension.class)` to `@RunWith(MockitoJUnitRunner.class)`
  2. </details>
  3. # 答案2
  4. **得分**: 3
  5. 调用 doFilter,将模拟的 ServletRequestServletResponse FilterChain 作为其参数传递。
  6. ```java
  7. @Test
  8. public void testDoFilter() {
  9. LoggingFilter filterUnderTest = new LoggingFilter();
  10. MockFilterChain mockChain = new MockFilterChain();
  11. MockServletRequest req = new MockServletRequest("/test.jsp");
  12. MockServletResponse rsp = new MockServletResponse();
  13. filterUnderTest.doFilter(req, rsp, mockChain);
  14. assertEquals("/test.jsp", rsp.getLastRedirect());
  15. }

在实际应用中,您会希望将设置移到 @Before setUp() 方法中,并编写更多的 @Test 方法来覆盖每个可能的执行路径。

您可能会使用模拟框架,比如 JMockMockito 来创建模拟,而不是我在这里使用的假设的 MockModeService 等。这是单元测试的方法,而不是集成测试。您只测试正在测试的单元(以及测试代码)。

英文:

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

  1. @Test
  2. public void testDoFilter() {
  3. LoggingFilter filterUnderTest = new LoggingFilter();
  4. MockFilterChain mockChain = new MockFilterChain();
  5. MockServletRequest req = new MockServletRequest(&quot;/test.jsp&quot;);
  6. MockServletResponse rsp = new MockServletResponse();
  7. filterUnderTest.doFilter(req, rsp, mockChain);
  8. assertEquals(&quot;/test.jsp&quot;,rsp.getLastRedirect());
  9. }

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

答案3

得分: 1

如果您在JUnit 5中使用AEM Mocks,代码可能如下所示:

  1. @ExtendWith(AemContextExtension.class)
  2. class SimpleFilterTest {
  3. private static final AemContext context = new AemContext(ResourceResolverType.RESOURCERESOLVER_MOCK);
  4. private static final String RESOURCE_PATH = "/content/test";
  5. private static final String SELECTOR_STRING = "selectors";
  6. private static SimpleFilter simpleFilter;
  7. private static FilterChain filterChain;
  8. @BeforeAll
  9. static void setup() {
  10. simpleFilter = context.registerService(SimpleFilter.class, new SimpleFilter());
  11. filterChain = context.registerService(FilterChain.class, new MockFilterChain());
  12. }
  13. @Test
  14. @DisplayName("GIVEN the request, WHEN is executed, THEN request should be filtered and contain corresponding header")
  15. void testDoFilter() throws ServletException, IOException {
  16. context.requestPathInfo().setResourcePath(RESOURCE_PATH);
  17. context.requestPathInfo().setSelectorString(SELECTOR_STRING);
  18. simpleFilter.doFilter(context.request(), context.response(), filterChain);
  19. assertEquals("true", context.response().getHeader("filtered"));
  20. }
  21. }

Mock

  1. public class MockFilterChain implements FilterChain {
  2. @Override
  3. public void doFilter(final ServletRequest request, final ServletResponse response) throws IOException, ServletException {
  4. // do nothing
  5. }
  6. }

一些简单的过滤器

  1. @Component(service = Filter.class)
  2. @SlingServletFilter(scope = SlingServletFilterScope.REQUEST)
  3. @ServiceRanking(-700)
  4. public class SimpleFilter implements Filter {
  5. @Override
  6. public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain filterChain) throws IOException, ServletException {
  7. final SlingHttpServletRequest slingRequest = (SlingHttpServletRequest) request;
  8. log.debug("request for {}, with selector {}", slingRequest.getRequestPathInfo().getResourcePath(),
  9. slingRequest.getRequestPathInfo().getSelectorString());
  10. final SlingHttpServletResponse slingResponse = (SlingHttpServletResponse) response;
  11. slingResponse.setHeader("filtered", "true");
  12. filterChain.doFilter(request, response);
  13. }
  14. @Override
  15. public void init(FilterConfig filterConfig) {
  16. }
  17. @Override
  18. public void destroy() {
  19. }
  20. }
英文:

If you use AEM Mocks with Junit5, then it could look something like this.

  1. @ExtendWith(AemContextExtension.class)
  2. class SimpleFilterTest {
  3. private static final AemContext context = new AemContext(ResourceResolverType.RESOURCERESOLVER_MOCK);
  4. private static final String RESOURCE_PATH = &quot;/content/test&quot;;
  5. private static final String SELECTOR_STRING = &quot;selectors&quot;;
  6. private static SimpleFilter simpleFilter;
  7. private static FilterChain filterChain;
  8. @BeforeAll
  9. static void setup() {
  10. simpleFilter = context.registerService(SimpleFilter.class, new SimpleFilter());
  11. filterChain = context.registerService(FilterChain.class, new MockFilterChain());
  12. }
  13. @Test
  14. @DisplayName(&quot;GIVEN the request, WHEN is executed, THEN request should be filtered and contain corresponding header&quot;)
  15. void testDoFilter() throws ServletException, IOException {
  16. context.requestPathInfo().setResourcePath(RESOURCE_PATH);
  17. context.requestPathInfo().setSelectorString(SELECTOR_STRING);
  18. simpleFilter.doFilter(context.request(), context.response(), filterChain);
  19. assertEquals(&quot;true&quot;, context.response().getHeader(&quot;filtered&quot;));
  20. }
  21. }

Mock

  1. public class MockFilterChain implements FilterChain {
  2. @Override
  3. public void doFilter(final ServletRequest request, final ServletResponse response) throws IOException, ServletException {
  4. // do nothing
  5. }
  6. }

Some simple filter

  1. @Component(service = Filter.class)
  2. @SlingServletFilter(scope = SlingServletFilterScope.REQUEST)
  3. @ServiceRanking(-700)
  4. public class SimpleFilter implements Filter {
  5. @Override
  6. public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain filterChain) throws IOException, ServletException {
  7. final SlingHttpServletRequest slingRequest = (SlingHttpServletRequest) request;
  8. log.debug(&quot;request for {}, with selector {}&quot;, slingRequest.getRequestPathInfo().getResourcePath(),
  9. slingRequest.getRequestPathInfo().getSelectorString());
  10. final SlingHttpServletResponse slingResponse = (SlingHttpServletResponse) response;
  11. slingResponse.setHeader(&quot;filtered&quot;, &quot;true&quot;);
  12. filterChain.doFilter(request, response);
  13. }
  14. @Override
  15. public void init(FilterConfig filterConfig) {
  16. }
  17. @Override
  18. public void destroy() {
  19. }
  20. }

huangapple
  • 本文由 发表于 2020年9月2日 21:07:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/63706202.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定