根据Spring Boot Docs,应自动检测嵌套@TestConfiguration
。
但是在我的测试代码中,当我运行整个测试类时,它是有问题的,即使我通过@Import
显式添加它也没有检测到。测试代码结构如下:
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@RunWith(SpringRunner.class)
//@Import(IntegrationTests.TestSecurityConfig.class)
public class IntegrationTests {
// test methods
// test configuration
@TestConfiguration
static class TestSecurityConfig {}
}
当我单独运行单个测试用例(测试方法)时,所有测试都按预期传递,但是当我直接运行测试类时,某些测试失败,@TestConfiguration
为不适用于测试。
此IntegrationTests
的完整代码为here。
更新: 我的代码中添加了一种解决方法,以便通过测试。
@TestComponent
@Slf4j
static class TestUserDetailsService implements UserDetailsService {
private final PasswordEncoder passwordEncoder;
TestUserDetailsService(PasswordEncoder passwordEncoder) {
this.passwordEncoder = passwordEncoder;
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
UserDetails user = User.withUsername("user")
.password(passwordEncoder.encode("password"))
.roles("USER")
.accountExpired(false)
.accountLocked(false)
.credentialsExpired(false)
.disabled(false)
.build();
UserDetails admin = User.withUsername("admin")
.password(passwordEncoder.encode("password"))
.roles("ADMIN")
.accountExpired(false)
.accountLocked(false)
.credentialsExpired(false)
.disabled(false)
.build();
log.debug("dummy user:" + user);
log.debug("dummy admin:" + admin);
if ("user".equals(username)) {
return user;
} else {
return admin;
}
}
}
@TestConfiguration
@Slf4j
@Import(TestUserDetailsService.class)
@Order(-1)
static class TestSecurityConfig extends WebSecurityConfigurerAdapter {
@Inject
PasswordEncoder passwordEncoder;
@Inject
UserDetailsService userDetailsService;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.httpBasic()
.and()
.authorizeRequests()
.antMatchers(HttpMethod.GET, "/posts/**").permitAll()
.antMatchers(HttpMethod.DELETE, "/posts/**").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.csrf().disable();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder);
}
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
}
仍有一些事情使我感到困惑。
@TestConfiguration
无法检测位于同一测试中的@TestComponent
,我必须添加@Import
来修复它。UserDetailsService
bean就足够了,它将为用户提供安全保障,但它在测试中无效。我必须配置一个WebSecurityConfigurerAdapter
并公开AuthenticationManager
进行测试,为什么?如上所述,如果没有为测试定义WebSecurityConfigurerAdapter
,则逐个运行测试就会更加困惑。@TestConfiguration
注释WebSecurityConfigurerAdapter
没有获得更高的订单,我必须在其上添加@Order
。我在想一个@TestConfiguration
bean应该自动获取Primary并在我的应用程序配置中替换bean,对吗?