使用MockMVC和@ComponentScan找不到springSecurityFilterChain bean

时间:2017-10-25 15:31:07

标签: java spring unit-testing spring-mvc spring-security

我正在使用弹簧MockMVC测试弹簧支架控制器。 我能够执行模拟http请求并验证响应。 我的设置自动装配了WebApplicationContext:

@RunWith(SpringRunner.class)
@WebAppConfiguration
@ContextConfiguration
public class MyTestClass {

@Autowired
private WebApplicationContext webAppContext;

private MockMvc mockMvc;

@Before
public void setup() {
    this.mockMvc = MockMvcBuilders.webAppContextSetup(this.webAppContext)
            .apply(springSecurity()).build();
}

告诉MockMVC要初始化并添加到上下文的控制器我有一个内部配置类:

@Configuration
@ComponentScan(
        basePackages = {"com.acme"},
        useDefaultFilters = false,
        includeFilters = {@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value={MyRestController.class, MyRestControllerDependency.class})
        })
@EnableWebMvc
static class MyTestClassConfig implements WebMvcConfigurer {

    @Bean
    public MyClassRepository myClassRepository() {
        return Mockito.mock(MyClassRepository.class);
    }

这就像一个魅力。 MockMVC使用加载MyRestController的上下文旋转容器,并提供MyRestController映射的url。 现在,一些MyRestControllers方法注释为:@PreAuthorize("hasAuthority('ADMINISTRATOR')")所以下一步是测试它。

阅读Spring安全测试指南的Integration部分 spring security and test-mockmvc  我似乎应该做的就是调用MockMvcBuilders .apply()函数调用中的org.springframework.security.test.web.servlet.setup.springSecurity()。

这不起作用,我得到:

java.lang.IllegalStateException: springSecurityFilterChain cannot be null. Ensure a Bean with the name springSecurityFilterChain implementing Filter is present or inject the Filter to be used.

我尝试将bean定义添加到我的内部配置类中,如下所示:

    Filter springSecurityFilterChain() {
        return new FilterChainProxy();
    }

虽然这确实提供了springSecurityFilterChain,但实例是空的,当我运行测试时,我得到一个NPE:

java.lang.NullPointerException
at org.springframework.security.web.FilterChainProxy.getFilters(FilterChainProxy.java:224)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)

可以理解的是,通过直接实例化FilterChainProxy,它确实是空的。

我怀疑我需要配置组件扫描以包含FilterChainProxy的spring实例。 如果是问题,我不知道应该包括哪些类。我尝试过包括所有课程:

        includeFilters = {@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value={TenantAPI.class, TenantManager.class}),
                          @ComponentScan.Filter(type = FilterType.REGEX, pattern="^org\\.springframework\\.security.*")})

但是这给出了同样的错误:“确保一个名为springSecurity的Bean ..”就像我在没有额外的Regex过滤器的情况下运行测试一样。

有什么人知道当我对MockMVC实例化的内部类很挑剔的时候我怎么能得到springSecurityFilterChain?

1 个答案:

答案 0 :(得分:2)

我假设您必须在某个@Configuration类扩展WebSecurityConfigurerAdapter?这是设置Spring安全性所需的配置。

您需要在测试配置中的组件扫描中包含此类。