使用 Spring-Test-MVC 单元测试 Spring-Security - 集成 FilterChain / ServletFilter

Posted

技术标签:

【中文标题】使用 Spring-Test-MVC 单元测试 Spring-Security - 集成 FilterChain / ServletFilter【英文标题】:Using Spring-Test-MVC to unit test Spring-Security - Integrating the FilterChain / ServletFilter 【发布时间】:2012-06-15 12:15:26 【问题描述】:

因此,我们几乎达到了测试驱动我们的 spring web-mvc 应用程序的目标。我们正在使用 Spring Security 来保护 URL 或方法,并且我们希望使用 Spring-Web-Mvc 来测试控制器。问题是:Spring 安全性依赖于 web.xml 中定义的 FilterChain:

<filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>FORWARD</dispatcher>
    <dispatcher>REQUEST</dispatcher>
</filter-mapping>

虽然 spring-web-mvc 即使使用 custom context loader 也只能加载通常的应用程序上下文内容:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(loader = WebContextLoader.class, locations = 
        "file:src/main/webapp/WEB-INF/servlet-context.xml", "file:src/main/webapp/WEB-INF/dw-manager-context.xml" )
public class MvcTest 

    @Inject
    protected MockMvc mockMvc;

    @Test
    public void loginRequiredTest() throws Exception 

        mockMvc.perform(get("/home")).andExpect(status().isOk()).andExpect(content().type("text/html;charset=ISO-8859-1"))
        .andExpect(content().string(containsString("Please Login")));
    


正如我们所看到的,我们设置了我们的网络应用程序,以便在调用 /home 时会提示匿名用户登录。这与 web.xml 一起工作正常,但我们不知道如何集成它进入我们的测试。

有没有办法给spring-test-mvc添加过滤器?

现在我在想我可能必须从GenericWebContextLoader 开始,深入了解实现RequestDispatcherMockRequestDipatcher,以某种方式在那里添加一个过滤器,然后告诉GenericWebContextLoader 使用我的实现.. . 但是我对整个网络堆栈非常陌生,并且更喜欢一个更简单的解决方案,可以帮助我避免深入研究这些东西......

有什么想法/解决方案吗?

我将如何手动添加过滤器? web.xml 不能是唯一这样做的地方...

谢谢!

【问题讨论】:

【参考方案1】:

也许您可以模拟过滤器链。在 Spring 中有一个 class 可以做到这一点。 代码看起来像:

     MockHttpServletRequest request = new MockHttpServletRequest();
     request.setServletPath("/foo/secure/super/somefile.html");

     MockHttpServletResponse response = new MockHttpServletResponse();
     MockFilterChain chain = new MockFilterChain(true);

     filterChainProxy.doFilter(request, response, chain);

然后你可以将 org.springframework.web.filter.DelegatingFilterProxy 实例添加到 链在你的代码中。 比如:

另见this论坛帖子。

【讨论】:

是的,我们也一直在考虑这些方面。就像我说的,我必须扩展 RequestDispatcher (MockRequestDipatcher) 的 spring-test-mvc 实现,覆盖 forward 方法,从当前上下文中获取filterChainProxy,然后在转发请求之前调用过滤器..或者可能使用切入点..我更喜欢以某种方式使用xml配置,因为它更接近原始配置,但看起来我们不会实现我们的愿望..

以上是关于使用 Spring-Test-MVC 单元测试 Spring-Security - 集成 FilterChain / ServletFilter的主要内容,如果未能解决你的问题,请参考以下文章

SpringMvc测试框架详解----服务端测试

如何使用线程执行单元测试? [复制]

如何使用 PHP 单元测试避免竞争条件

单元测试逼近算法

单元测试-从表格获取测试数据

使用 JUnit 和 Mockito 对 DAO 类进行单元测试