java - 使用 MockMVC 和 @ComponentScan 找不到 springSecurityFilterChain bean

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

我正在使用 spring MockMVC 测试 Spring 休息 Controller 。 我能够执行模拟 http 请求并验证响应。 我的设置 Autowiring 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 初始化哪些 Controller 并将其添加到上下文中,我有一个内部配置类:

@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 安全测试指南的集成部分 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,确实是空的。

我怀疑我需要配置我的组件扫描以包括 Springs 的 FilterChainProxy 实例。 如果这就是问题所在,我不知道我应该包括哪些类(class)。我尝试过包括所有类(class):

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

但这给出了相同的错误:“确保一个名为 springSecurity 的 Bean..”,就像我在没有附加正则表达式过滤器的情况下运行测试时一样。

有谁知道当我对让 MockMVC 实例化的内部类挑剔时如何获得 springSecurityFilterChain ?

最佳答案

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

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

关于java - 使用 MockMVC 和 @ComponentScan 找不到 springSecurityFilterChain bean,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46936469/

相关文章:

java - 无限递归嵌套对象

Java ArrayBlockingQueue 取源码

java - 在嵌入式 Tomcat 7 中部署 WAR

unit-testing - react-navigation-hooks : How to test useFocusEffect

java - 为什么 java.util.Scanner next().charAt(0) 返回 "{",而我的 nextCharIs(scanner ,"{") 方法返回 false?

java - 如何在 Java 中使用 pin/密码加载 Windows-MY keystore ?

java - 为什么会出现 "org.hibernate.hql.internal.ast.QuerySyntaxException: customer is not mapped [from customer]"错误

java - Couchbase 使用 key 获取给定日期范围内的文档

java - org.springframework.boot.context.embedded.PortInUseException : Port 80 is already in use

javascript - 避免 JavaScript 测试中的误报