问题描述
如何用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() {}
}
解决方法
调用doFilter并将模拟ServletRequest,ServletResponse和FilterChain作为其参数。
@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
等。我在这里使用过。
与集成测试相反,这是一种单元测试方法。您仅在行使被测设备(和测试代码)。
,您可以使用以下代码对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)
如果将AEM Mocks与Junit5一起使用,则可能看起来像这样。
@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() {
}
}