英文:
How do I unit test a Servlet Filter with jUnit? ServletRequest, ServletResponse, FilterChain
问题
@SlingFilter(order = -700, scope = SlingFilterScope.REQUEST)
public class LoggingFilter implements Filter {
private final Logger logger = LoggerFactory.getLogger(getClass());
@Override
public void doFilter(final ServletRequest request, final ServletResponse response,
final FilterChain filterChain) throws IOException, ServletException {
final SlingHttpServletRequest slingRequest = (SlingHttpServletRequest) request;
logger.debug("request for {}, with selector {}", slingRequest
.getRequestPathInfo().getResourcePath(), slingRequest
.getRequestPathInfo().getSelectorString());
filterChain.doFilter(request, response);
}
@Override
public void init(FilterConfig filterConfig) {}
@Override
public void destroy() {}
}
英文:
How to properly cover Filter with JUnit?
@SlingFilter(order = -700, scope = SlingFilterScope.REQUEST)
public class LoggingFilter implements Filter {
private final Logger logger = LoggerFactory.getLogger(getClass());
@Override
public void doFilter(final ServletRequest request, final ServletResponse response,
final FilterChain filterChain) throws IOException, ServletException {
final SlingHttpServletRequest slingRequest = (SlingHttpServletRequest) request;
logger.debug("request for {}, with selector {}", slingRequest
.getRequestPathInfo().getResourcePath(), slingRequest
.getRequestPathInfo().getSelectorString());
filterChain.doFilter(request, response);
}
@Override
public void init(FilterConfig filterConfig) {}
@Override
public void destroy() {}
}
答案1
得分: 4
@ExtendWith(MockitoExtension.class)
public class LoggingFilterTest {
@InjectMocks
private LoggingFilter loggingFilter;
@Mock
private ServletRequest request;
@Mock
private ServletResponse response;
@Mock
private FilterChain filterChain;
@Mock
private RequestPathInfo requestPathInfo;
@Test
public void testDoFilter() throws IOException, ServletException {
Mockito.when(request.getResourcePath()).thenReturn(requestPathInfo);
Mockito.when(requestPathInfo.getResourcePath()).thenReturn("/testPath", "selectorString");
Mockito.doNothing().when(filterChain).doFilter(Mockito.eq(request), Mockito.eq(response));
loggingFilter.doFilter(request, response, filterChain);
Mockito.verify(filterChain, times(1)).doFilter(Mockito.eq(request), Mockito.eq(response));
}
}
If you are using junit4
, then change @ExtendWith(MockitoExtension.class)
to @RunWith(MockitoJUnitRunner.class)
.
<details>
<summary>英文:</summary>
You can use below code for your testing with `Junit-5`
@ExtendWith(MockitoExtension.class)
public class LoggingFilterTest{
@InjectMocks
private LoggingFilter loggingFilter;
@Mock
private ServletRequest request
@Mock
private ServletResponse response
@Mock
private FilterChain filterChain
@Mock
private RequestPathInfo requestPathInfo;
@Test
public void testDoFilter() throws IOException, ServletException{
Mockito.when(request.getResourcePath()).thenReturn(requestPathInfo);
Mockito.when(requestPathInfo.getResourcePath()).thenReturn("/testPath", "selectorString");
Mockito.doNothing().when(filterChain).doFilter(Mockito.eq(request), Mockito.eq(response));
loggingFilter.doFilter(request, response, filterChain);
Mockito.verify(filterChain, times(1)).doFilter(Mockito.eq(request), Mockito.eq(response));
}
}
If you are using `junit4` then change `@ExtendWith(MockitoExtension.class)` to `@RunWith(MockitoJUnitRunner.class)`
</details>
# 答案2
**得分**: 3
调用 doFilter,将模拟的 ServletRequest、ServletResponse 和 FilterChain 作为其参数传递。
```java
@Test
public void testDoFilter() {
LoggingFilter filterUnderTest = new LoggingFilter();
MockFilterChain mockChain = new MockFilterChain();
MockServletRequest req = new MockServletRequest("/test.jsp");
MockServletResponse rsp = new MockServletResponse();
filterUnderTest.doFilter(req, rsp, mockChain);
assertEquals("/test.jsp", rsp.getLastRedirect());
}
在实际应用中,您会希望将设置移到 @Before setUp()
方法中,并编写更多的 @Test
方法来覆盖每个可能的执行路径。
您可能会使用模拟框架,比如 JMock
或 Mockito
来创建模拟,而不是我在这里使用的假设的 MockModeService
等。这是单元测试的方法,而不是集成测试。您只测试正在测试的单元(以及测试代码)。
英文:
Invoke doFilter passing the mock ServletRequest, ServletResponse and FilterChain as its parameters.
@Test
public void testDoFilter() {
LoggingFilter filterUnderTest = new LoggingFilter();
MockFilterChain mockChain = new MockFilterChain();
MockServletRequest req = new MockServletRequest("/test.jsp");
MockServletResponse rsp = new MockServletResponse();
filterUnderTest.doFilter(req, rsp, mockChain);
assertEquals("/test.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).
答案3
得分: 1
如果您在JUnit 5中使用AEM Mocks,代码可能如下所示:
@ExtendWith(AemContextExtension.class)
class SimpleFilterTest {
private static final AemContext context = new AemContext(ResourceResolverType.RESOURCERESOLVER_MOCK);
private static final String RESOURCE_PATH = "/content/test";
private static final String SELECTOR_STRING = "selectors";
private static SimpleFilter simpleFilter;
private static FilterChain filterChain;
@BeforeAll
static void setup() {
simpleFilter = context.registerService(SimpleFilter.class, new SimpleFilter());
filterChain = context.registerService(FilterChain.class, new MockFilterChain());
}
@Test
@DisplayName("GIVEN the request, WHEN is executed, THEN request should be filtered and contain corresponding header")
void testDoFilter() throws ServletException, IOException {
context.requestPathInfo().setResourcePath(RESOURCE_PATH);
context.requestPathInfo().setSelectorString(SELECTOR_STRING);
simpleFilter.doFilter(context.request(), context.response(), filterChain);
assertEquals("true", context.response().getHeader("filtered"));
}
}
Mock
public class MockFilterChain implements FilterChain {
@Override
public void doFilter(final ServletRequest request, final ServletResponse response) throws IOException, ServletException {
// do nothing
}
}
一些简单的过滤器
@Component(service = Filter.class)
@SlingServletFilter(scope = SlingServletFilterScope.REQUEST)
@ServiceRanking(-700)
public class SimpleFilter implements Filter {
@Override
public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain filterChain) throws IOException, ServletException {
final SlingHttpServletRequest slingRequest = (SlingHttpServletRequest) request;
log.debug("request for {}, with selector {}", slingRequest.getRequestPathInfo().getResourcePath(),
slingRequest.getRequestPathInfo().getSelectorString());
final SlingHttpServletResponse slingResponse = (SlingHttpServletResponse) response;
slingResponse.setHeader("filtered", "true");
filterChain.doFilter(request, response);
}
@Override
public void init(FilterConfig filterConfig) {
}
@Override
public void destroy() {
}
}
英文:
If you use AEM Mocks with Junit5, then it could look something like this.
@ExtendWith(AemContextExtension.class)
class SimpleFilterTest {
private static final AemContext context = new AemContext(ResourceResolverType.RESOURCERESOLVER_MOCK);
private static final String RESOURCE_PATH = "/content/test";
private static final String SELECTOR_STRING = "selectors";
private static SimpleFilter simpleFilter;
private static FilterChain filterChain;
@BeforeAll
static void setup() {
simpleFilter = context.registerService(SimpleFilter.class, new SimpleFilter());
filterChain = context.registerService(FilterChain.class, new MockFilterChain());
}
@Test
@DisplayName("GIVEN the request, WHEN is executed, THEN request should be filtered and contain corresponding header")
void testDoFilter() throws ServletException, IOException {
context.requestPathInfo().setResourcePath(RESOURCE_PATH);
context.requestPathInfo().setSelectorString(SELECTOR_STRING);
simpleFilter.doFilter(context.request(), context.response(), filterChain);
assertEquals("true", context.response().getHeader("filtered"));
}
}
Mock
public class MockFilterChain implements FilterChain {
@Override
public void doFilter(final ServletRequest request, final ServletResponse response) throws IOException, ServletException {
// do nothing
}
}
Some simple filter
@Component(service = Filter.class)
@SlingServletFilter(scope = SlingServletFilterScope.REQUEST)
@ServiceRanking(-700)
public class SimpleFilter implements Filter {
@Override
public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain filterChain) throws IOException, ServletException {
final SlingHttpServletRequest slingRequest = (SlingHttpServletRequest) request;
log.debug("request for {}, with selector {}", slingRequest.getRequestPathInfo().getResourcePath(),
slingRequest.getRequestPathInfo().getSelectorString());
final SlingHttpServletResponse slingResponse = (SlingHttpServletResponse) response;
slingResponse.setHeader("filtered", "true");
filterChain.doFilter(request, response);
}
@Override
public void init(FilterConfig filterConfig) {
}
@Override
public void destroy() {
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论