如何在集成测试中使用 spring 安全性?
How to use spring security in integration tests?
我有以下 WebSecurityConfigurerAdapter
实现:
@Configuration
@Order(0)
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
private static final List<String> permittedPaths = asList();
private static final String protectedPath = "";
private final UserDetailsServiceImpl userDetailsService;
private final JwtAuthenticationProvider jwtAuthenticationProvider;
private final DataSource dataSource;
public SecurityConfiguration(
UserDetailsServiceImpl userDetailsService,
JwtAuthenticationProvider jwtAuthenticationProvider,
DataSource dataSource
) {
this.userDetailsService = userDetailsService;
this.jwtAuthenticationProvider = jwtAuthenticationProvider;
this.dataSource = dataSource;
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
protected void configure(HttpSecurity http) throws Exception {}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
auth.authenticationProvider(jwtAuthenticationProvider);
auth.jdbcAuthentication().dataSource(dataSource)
.usersByUsernameQuery("")
.authoritiesByUsernameQuery("")
.passwordEncoder(passwordEncoder());
}
}
此安全性适用于正常的 运行ning 应用程序。但在测试中 - 失败了。
我有一个像这样的集成测试:
@WebMvcTest(SomeController.class)
@Import({ErrorHandlerConfiguration.class})
class SomeControllerItTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private RegistrationService registrationService;
@Test
void shouldConfirmRegistration() {}
}
在 运行 之后,我收到以下错误:
Caused by:
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'securityConfiguration' defined in file
[SecurityConfiguration.class]: Unsatisfied dependency expressed
through constructor parameter 0; nested exception is
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
qualifying bean of type 'UserDetailsServiceImpl' available: expected
at least 1 bean which qualifies as autowire candidate. Dependency
annotations: {}
当我添加到这个测试时 SecurityConfiguration
class beans:
@MockBean
private JwtAuthenticationProvider jwtAuthenticationProvider;
@MockBean
private UserDetailsServiceImpl userDetailsService;
@MockBean
private DataSource dataSource;
测试 运行 正常,没有任何 NoSuchBeanDefinitionException
异常。
这个解决方案对我来说还不够。有没有其他方法可以避免将安全 bean 放入每个集成测试中?
我尝试使用:
@Import({ErrorHandlerConfiguration.class, SecurityConfiguration.class})
@ContextConfiguration(classes = {SecurityConfiguration.class})
没有任何结果。
(为简洁起见删除了方法主体和一些字符串)
// 编辑
附上缺失的 classes,注入到 SecurityConfiguration
:
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
//method implementation
}
@Component
public class JwtAuthenticationProvider implements AuthenticationProvider {
//method implementation
}
这是一个合格的猜测,但由于某种原因您没有发布缺少的 class UserDetailsServiceImpl
。
如果您阅读有关 WebMvcTest
的文档,它指出:
@WebMvcTest
auto-configures the Spring MVC infrastructure and limits scanned beans to @Controller
, @ControllerAdvice
, @JsonComponent
, Converter
, GenericConverter
, Filter
, HandlerInterceptor
, WebMvcConfigurer
, and HandlerMethodArgumentResolver
.
Regular @Component
and @ConfigurationProperties
beans are not scanned when the @WebMvcTest
annotation is used. @EnableConfigurationProperties
can be used to include @ConfigurationProperties
beans.
所以我猜你的豆子因为这个原因没有被捡起,它都在 docs.
中说明了
但如前所述,这是一个猜测,因为出于某种原因您没有发布缺少的代码供我们查看,并且有几个未知数,如空构造函数和其他空函数.
@WebMvcTest(
value = SomeController.class,
excludeAutoConfiguration = SecurityAutoConfiguration.class,
excludeFilters = @ComponentScan.Filter(
type = FilterType.ASSIGNABLE_TYPE,
classes = WebSecurityConfigurer.class))
@AutoConfigureMockMvc(addFilters = false)
public class SomeControllerTest {
@Autowired
MockMvc mockMvc;
...
}
我有以下 WebSecurityConfigurerAdapter
实现:
@Configuration
@Order(0)
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
private static final List<String> permittedPaths = asList();
private static final String protectedPath = "";
private final UserDetailsServiceImpl userDetailsService;
private final JwtAuthenticationProvider jwtAuthenticationProvider;
private final DataSource dataSource;
public SecurityConfiguration(
UserDetailsServiceImpl userDetailsService,
JwtAuthenticationProvider jwtAuthenticationProvider,
DataSource dataSource
) {
this.userDetailsService = userDetailsService;
this.jwtAuthenticationProvider = jwtAuthenticationProvider;
this.dataSource = dataSource;
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
protected void configure(HttpSecurity http) throws Exception {}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
auth.authenticationProvider(jwtAuthenticationProvider);
auth.jdbcAuthentication().dataSource(dataSource)
.usersByUsernameQuery("")
.authoritiesByUsernameQuery("")
.passwordEncoder(passwordEncoder());
}
}
此安全性适用于正常的 运行ning 应用程序。但在测试中 - 失败了。 我有一个像这样的集成测试:
@WebMvcTest(SomeController.class)
@Import({ErrorHandlerConfiguration.class})
class SomeControllerItTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private RegistrationService registrationService;
@Test
void shouldConfirmRegistration() {}
}
在 运行 之后,我收到以下错误:
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'securityConfiguration' defined in file [SecurityConfiguration.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'UserDetailsServiceImpl' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
当我添加到这个测试时 SecurityConfiguration
class beans:
@MockBean
private JwtAuthenticationProvider jwtAuthenticationProvider;
@MockBean
private UserDetailsServiceImpl userDetailsService;
@MockBean
private DataSource dataSource;
测试 运行 正常,没有任何 NoSuchBeanDefinitionException
异常。
这个解决方案对我来说还不够。有没有其他方法可以避免将安全 bean 放入每个集成测试中?
我尝试使用:
@Import({ErrorHandlerConfiguration.class, SecurityConfiguration.class})
@ContextConfiguration(classes = {SecurityConfiguration.class})
没有任何结果。
(为简洁起见删除了方法主体和一些字符串)
// 编辑
附上缺失的 classes,注入到 SecurityConfiguration
:
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
//method implementation
}
@Component
public class JwtAuthenticationProvider implements AuthenticationProvider {
//method implementation
}
这是一个合格的猜测,但由于某种原因您没有发布缺少的 class UserDetailsServiceImpl
。
如果您阅读有关 WebMvcTest
的文档,它指出:
@WebMvcTest
auto-configures the Spring MVC infrastructure and limits scanned beans to@Controller
,@ControllerAdvice
,@JsonComponent
,Converter
,GenericConverter
,Filter
,HandlerInterceptor
,WebMvcConfigurer
, andHandlerMethodArgumentResolver
.
Regular
@Component
and@ConfigurationProperties
beans are not scanned when the@WebMvcTest
annotation is used.@EnableConfigurationProperties
can be used to include@ConfigurationProperties
beans.
所以我猜你的豆子因为这个原因没有被捡起,它都在 docs.
中说明了但如前所述,这是一个猜测,因为出于某种原因您没有发布缺少的代码供我们查看,并且有几个未知数,如空构造函数和其他空函数.
@WebMvcTest(
value = SomeController.class,
excludeAutoConfiguration = SecurityAutoConfiguration.class,
excludeFilters = @ComponentScan.Filter(
type = FilterType.ASSIGNABLE_TYPE,
classes = WebSecurityConfigurer.class))
@AutoConfigureMockMvc(addFilters = false)
public class SomeControllerTest {
@Autowired
MockMvc mockMvc;
...
}