JUnit 5 Spring 安全 WebMvcTest 没有 PasswordEncoder 类型的 bean
JUnit 5 Spring Security WebMvcTest no bean of type PasswordEncoder
我正在尝试测试一个基本的页面控制器,其中 returns 一个 thymeleaf 模板。
控制器看起来像这样:
@Controller
public class EntryOverviewController {
@GetMapping(ApplicationConstants.URL_ENTRY_OVERVIEW)
public String getPage(Model model) {
return ApplicationConstants.VIEW_ENTRY_OVERVIEW;
}
我的 WebSecurityConfig 如下所示:
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
@Slf4j
@Configuration
@Order(1005)
public class WebSecurityConfig {
@Configuration
@Order(1005)
public class WebAppSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/**").permitAll().and().headers().defaultsDisabled().cacheControl().and()
.httpStrictTransportSecurity().includeSubDomains(false).maxAgeInSeconds(31536000).and().frameOptions().disable().and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.ALWAYS);
}
}
@Order(1004)
@Configuration
public static class ActuatorWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
@Autowired
private PasswordEncoder passwordEncoder;
@Value("${management.endpoints.web.access.user}")
private String user;
@Value("${management.endpoints.web.access.password}")
private String password;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.requestMatcher(EndpointRequest.toAnyEndpoint()).authorizeRequests().requestMatchers(EndpointRequest.to(HealthEndpoint.class))
.permitAll().anyRequest().authenticated().and().httpBasic().and().sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser(user).password(passwordEncoder.encode(password)).roles();
}
}
/** Password encoder */
@Bean(name = "passwordEncoder")
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
我的测试是这样的:
@ExtendWith(SpringExtension.class)
@WebMvcTest(EntryOverviewController.class)
class EntryOverviewControllerTest {
@Autowired
private MockMvc mvc;
@WithMockUser(value = "user")
@Test
public void testCorrectModel() throws Exception {
mvc.perform(get(ApplicationConstants.URL_ENTRY_OVERVIEW)).andExpect(status().isOk()).andExpect(model().attributeExists("registerEntry"))
.andExpect(view().name(ApplicationConstants.VIEW_ENTRY_OVERVIEW));
}
}
现在,当我想执行我的 junit 5 测试时,它失败并显示错误消息 org.springframework.beans.factory.NoSuchBeanDefinitionException:没有 'org.springframework.security.crypto.password.PasswordEncoder' 类型的合格 bean 可用:预计至少有 1 个符合自动装配候选条件的 bean .依赖注解:{@org.springframework.beans.factory.annotation.Autowired(required=true)}
当我用@MockBean 模拟 passwordEncoder 时,它给出了错误 password cannot be null。
不用自动装配 PasswordEncoder,只需使用 passwordEncoder()。在此处查看 bean 间依赖关系 https://docs.spring.io/spring-framework/docs/3.2.x/spring-framework-reference/html/beans.html#beans-java-configuration-annotation。
您想命名编码器 bean 的原因是什么?您没有 passwordEncoder 的多个实现。
@Bean(name = "passwordEncoder")
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
我认为 spring 在模拟这个实现时有问题。相反,你可以
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
它应该可以工作。
我通过简单地更改 class 注释解决了这个问题。
@WebMvcTest(EntryOverviewController.class)
@Import(WebSecurityConfig.class)
class EntryOverviewControllerTest {
...
}
所以我添加了 @Import 语句并且它起作用了
我正在尝试测试一个基本的页面控制器,其中 returns 一个 thymeleaf 模板。 控制器看起来像这样:
@Controller
public class EntryOverviewController {
@GetMapping(ApplicationConstants.URL_ENTRY_OVERVIEW)
public String getPage(Model model) {
return ApplicationConstants.VIEW_ENTRY_OVERVIEW;
}
我的 WebSecurityConfig 如下所示:
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
@Slf4j
@Configuration
@Order(1005)
public class WebSecurityConfig {
@Configuration
@Order(1005)
public class WebAppSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/**").permitAll().and().headers().defaultsDisabled().cacheControl().and()
.httpStrictTransportSecurity().includeSubDomains(false).maxAgeInSeconds(31536000).and().frameOptions().disable().and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.ALWAYS);
}
}
@Order(1004)
@Configuration
public static class ActuatorWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
@Autowired
private PasswordEncoder passwordEncoder;
@Value("${management.endpoints.web.access.user}")
private String user;
@Value("${management.endpoints.web.access.password}")
private String password;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.requestMatcher(EndpointRequest.toAnyEndpoint()).authorizeRequests().requestMatchers(EndpointRequest.to(HealthEndpoint.class))
.permitAll().anyRequest().authenticated().and().httpBasic().and().sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser(user).password(passwordEncoder.encode(password)).roles();
}
}
/** Password encoder */
@Bean(name = "passwordEncoder")
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
我的测试是这样的:
@ExtendWith(SpringExtension.class)
@WebMvcTest(EntryOverviewController.class)
class EntryOverviewControllerTest {
@Autowired
private MockMvc mvc;
@WithMockUser(value = "user")
@Test
public void testCorrectModel() throws Exception {
mvc.perform(get(ApplicationConstants.URL_ENTRY_OVERVIEW)).andExpect(status().isOk()).andExpect(model().attributeExists("registerEntry"))
.andExpect(view().name(ApplicationConstants.VIEW_ENTRY_OVERVIEW));
}
}
现在,当我想执行我的 junit 5 测试时,它失败并显示错误消息 org.springframework.beans.factory.NoSuchBeanDefinitionException:没有 'org.springframework.security.crypto.password.PasswordEncoder' 类型的合格 bean 可用:预计至少有 1 个符合自动装配候选条件的 bean .依赖注解:{@org.springframework.beans.factory.annotation.Autowired(required=true)}
当我用@MockBean 模拟 passwordEncoder 时,它给出了错误 password cannot be null。
不用自动装配 PasswordEncoder,只需使用 passwordEncoder()。在此处查看 bean 间依赖关系 https://docs.spring.io/spring-framework/docs/3.2.x/spring-framework-reference/html/beans.html#beans-java-configuration-annotation。
您想命名编码器 bean 的原因是什么?您没有 passwordEncoder 的多个实现。
@Bean(name = "passwordEncoder")
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
我认为 spring 在模拟这个实现时有问题。相反,你可以
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
它应该可以工作。
我通过简单地更改 class 注释解决了这个问题。
@WebMvcTest(EntryOverviewController.class)
@Import(WebSecurityConfig.class)
class EntryOverviewControllerTest {
...
}
所以我添加了 @Import 语句并且它起作用了