尝试使用 MockHttpServletResponse 测试 ResponseHeaderFilter 内的 HttpServletResponseWrapper

发布于 2025-01-02 12:49:43 字数 5589 浏览 2 评论 0原文

我正在尝试对下面的 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

国际总奸 2025-01-09 12:49:43

实际上,您正在测试的代码 ResponseHeaderFilter 仅在 FilterChain 中添加或注册匿名 HttpServletResponseWrapper

chain.doFilter(request, new HttpServletResponseWrapper(response) {
    public void setHeader(String name, String value) { ... }
});

FilterChain 是由容器本身执行。您的测试代码除了传递 FilterChain 引用之外什么也不做。

我不知道测试中 FilterChain 的真实类型,但不是断言标签已被删除 (assertThat((String)response.getHeader("ETag")),而是(nullValue()));) 我会将您的测试分为两个不同的测试。

  1. 将匿名 HttpServletResponseWrapper 替换为可称为 EtagRemoverHttpServletResponseWrapper 的完整类型,并进行单元测试,在 wrapper.setHeader(.. .) 省略 etag 头。

  2. 您的 ResponseHeaderFilter 上的第一个将断言 chain 包含 ETagRemoverHttpServletResponseWrapper 类型的引用

希望有帮助。

Actually the code you are testing ResponseHeaderFilter only adds or register an anonymous HttpServletResponseWrapper in the FilterChain :

chain.doFilter(request, new HttpServletResponseWrapper(response) {
    public void setHeader(String name, String value) { ... }
});

And the FilterChain is executed by the container itself. Your test code does nothing but passing a FilterChain 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.

  1. Replace the anonymous HttpServletResponseWrapper by a full type that can be called EtagRemoverHttpServletResponseWrapper and make a unit test that will actually assert that on wrapper.setHeader(...) it etag header is omitted.

  2. The first on your ResponseHeaderFilter which will assert that the chain contains a reference of type ETagRemoverHttpServletResponseWrapper

Hope that helps.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文