如何用JUnit正确覆盖Filter?
@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() {}
}
您可以使用以下代码对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));
}
}
如果使用junit4
,则将@ExtendWith(MockitoExtension.class)
更改为@RunWith(MockitoJUnitRunner.class)
@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
等。
这是一种单元测试方法,而不是集成测试。您只是在练习测试中的单元(以及测试代码(。
如果您在Junit5中使用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"));
}
}
模拟
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() {
}
}