我正在尝试对下面的ResponseHeaderFilter进行单元测试,但发现此单元测试失败:
@Test
public void testDoFilterWithOmmissableInitParameters_ETag()
throws IOException, ServletException {
// Add allowableUserAgents initParameters
MockFilterConfig filterConfig = new MockFilterConfig();
filterConfig.addInitParameter("allowableUserAgents", "avaya");
// Add allowableUserAgents initParameters
filterConfig.addInitParameter(OMIT_KEY, OMIT_VALUE);
// Set user-agent
request.addHeader("user-agent", "avaya");
response.addHeader("ETag", "someEtagHash");
filter.init(filterConfig);
filter.doFilter(request, response, chain);
// THIS ASSERTION FAILS:
assertThat((String)response.getHeader("ETag"), is(nullValue()));
}
具体来说,我在调试模式下运行它时的setHeader()方法永远不会被调用:
chain.doFilter(request,
new HttpServletResponseWrapper(response) {
public void setHeader(String name, String value) {
//if (!(name != null && omitHeaders.contains(name.toUpperCase()))) {
if (name != null && omitHeaders.contains(name)) {
super.setHeader(name, value);
}
}
});
调试器到达新HttpServletResponseWrapper(响应)的行,但实际上并没有执行setHeader方法。
这是整个班级本身:
public class ResponseHeaderFilter implements Filter {
private static final Logger logger = LoggerFactory.getLogger(ResponseHeaderFilter.class);
Map<String, String> additionalHeaders = new HashMap<String, String>();
Set<String> omitHeaders = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
Set<String> allowableUserAgents = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
boolean allowFromAllUserAgents = false;
public void doFilter(final ServletRequest request,
final ServletResponse res,
final FilterChain chain)
throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
String userAgent = ((HttpServletRequest) request).getHeader("user-agent");
if (allowFromAllUserAgents
|| (userAgent != null && allowableUserAgents.contains(userAgent))
) {
logger.debug("apply ResponseHeader rules for user agent [{}]", userAgent);
for (Map.Entry<String, String> entry : additionalHeaders.entrySet()) {
response.addHeader(entry.getKey(), entry.getValue());
}
chain.doFilter(request,
new HttpServletResponseWrapper(response) {
public void setHeader(String name, String value) {
//if (!(name != null && omitHeaders.contains(name.toUpperCase()))) {
if (name != null && omitHeaders.contains(name)) {
super.setHeader(name, value);
}
}
});
} else {
logger.debug("User agent [{}] is not an allowable agent for this filter", userAgent);
chain.doFilter(request, res);
}
}
/**
* Called once during start-up
*
* @param filterConfig for Filter configuration
*/
public void init(final FilterConfig filterConfig) {
logger.info("*** ResponseHeaderFilter.init() ***");
// set the provided HTTP response parameters
for (Enumeration e = filterConfig.getInitParameterNames(); e.hasMoreElements(); ) {
String headerName = (String) e.nextElement();
String headerValue = filterConfig.getInitParameter(headerName);
// Add the list of allowable user-agents
// cannot be null: if (headerName != null) {
if (headerName.equalsIgnoreCase("allowableUserAgents")) {
// omit
parseToUpperCaseElements(headerValue, allowableUserAgents);
logger.debug("allowable user-agent's {}", allowableUserAgents);
} else if (headerName.equalsIgnoreCase("allowFromAllUserAgents")) {
allowFromAllUserAgents = Boolean.parseBoolean(headerValue);
logger.debug("allowFromAllUserAgents {}", allowFromAllUserAgents);
} else if (headerName.equalsIgnoreCase("omit")) {
parseToUpperCaseElements(headerValue, omitHeaders);
logger.debug("Omit headers {}", omitHeaders);
} else {
additionalHeaders.put(headerName, headerValue);
logger.debug("adding header [{}] with value [{}]", headerName, headerValue);
}
//}
}
}
protected final void parseToUpperCaseElements(final String str, final Set<String> elementKeys) {
String[] words = str.split(",");
for (String s : words) {
elementKeys.add(s.trim().toUpperCase());
}
}
public void destroy() {
logger.debug("destroy");
}
}
此过滤器在运行时实际上有效,并且删除了ETag标头,但是当我尝试使用Cobertura进行代码覆盖时,该方法未经过测试。
答案 0 :(得分:0)
实际上,您正在测试ResponseHeaderFilter
的代码只会在HttpServletResponseWrapper
中添加或注册匿名FilterChain
:
chain.doFilter(request, new HttpServletResponseWrapper(response) {
public void setHeader(String name, String value) { ... }
});
FilterChain
由容器本身执行。您的测试代码除了传递FilterChain
引用外什么都不做。
我不知道您的测试中FilterChain
的真实类型,但是我没有断言标记被移除(assertThat((String)response.getHeader("ETag"), is(nullValue()));
),而是将测试分成两个不同的测试。
将匿名HttpServletResponseWrapper
替换为可以称为EtagRemoverHttpServletResponseWrapper
的完整类型,并进行单元测试,实际上在wrapper.setHeader(...)
上断言etag标题被省略。< / p>
ResponseHeaderFilter
上的第一个会断言chain
包含ETagRemoverHttpServletResponseWrapper
类型的引用
希望有所帮助。