尝试使用 MockHttpServletResponse 测试 ResponseHeaderFilter 内的 HttpServletResponseWrapper
我正在尝试对下面的 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);
}
}
});
调试器到达 new HttpServletResponseWrapper(response) 的行,但没有实际执行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 进行代码覆盖时,该方法未经过测试。
I am trying to unit test the below ResponseHeaderFilter but find that this unit test fails:
@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()));
}
Specifically, the setHeader() method when I run this in debug mode is NEVER called:
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);
}
}
});
The debugger gets to the line for new HttpServletResponseWrapper(response) but does not actually execute the setHeader method.
here is the entire class itself:
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");
}
}
This filter DOES actually work when running and DOES remove the ETag header, but when I am trying to use Cobertura for code coverage, that method is not tested.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
实际上,您正在测试的代码
ResponseHeaderFilter
仅在FilterChain
中添加或注册匿名HttpServletResponseWrapper
:而
FilterChain
是由容器本身执行。您的测试代码除了传递FilterChain
引用之外什么也不做。我不知道测试中
FilterChain
的真实类型,但不是断言标签已被删除 (assertThat((String)response.getHeader("ETag")),而是(nullValue()));
) 我会将您的测试分为两个不同的测试。将匿名
HttpServletResponseWrapper
替换为可称为EtagRemoverHttpServletResponseWrapper
的完整类型,并进行单元测试,在wrapper.setHeader(.. .)
省略 etag 头。您的
ResponseHeaderFilter
上的第一个将断言chain
包含ETagRemoverHttpServletResponseWrapper
类型的引用希望有帮助。
Actually the code you are testing
ResponseHeaderFilter
only adds or register an anonymousHttpServletResponseWrapper
in theFilterChain
:And the
FilterChain
is executed by the container itself. Your test code does nothing but passing aFilterChain
reference.I don't know the real type of your
FilterChain
in your test, but instead of asserting that the tag got removed (assertThat((String)response.getHeader("ETag"), is(nullValue()));
) I would split your test in two different test.Replace the anonymous
HttpServletResponseWrapper
by a full type that can be calledEtagRemoverHttpServletResponseWrapper
and make a unit test that will actually assert that onwrapper.setHeader(...)
it etag header is omitted.The first on your
ResponseHeaderFilter
which will assert that thechain
contains a reference of typeETagRemoverHttpServletResponseWrapper
Hope that helps.