有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java JUnit 5 Spring安全WebMvcTest没有PasswordEncoder类型的bean

我正在测试一个基本的页面控制器,它返回一个thymeleaf模板。 控制器如下所示:

@Controller
public class EntryOverviewController {

    @GetMapping(ApplicationConstants.URL_ENTRY_OVERVIEW)
    public String getPage(Model model) {

        return ApplicationConstants.VIEW_ENTRY_OVERVIEW;
    }

我的Web安全配置如下所示:

@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));
    }

}

现在,当我想执行JUnit5测试时,它失败了,并显示错误消息org。springframework。豆。工厂NoSuchBeanDefinitionException:没有类型为“org”的符合条件的bean。springframework。安全加密。暗语PasswordEncoder'可用:至少需要1个符合autowire候选条件的bean。依赖项注释:{@org.springframework.beans.factory.annotation.Autowired(required=true)}

当我用@MockBean模拟passwordEncoder时,它给出了错误密码不能为null


共 (3) 个答案

  1. # 2 楼答案

    您想给编码器bean命名有什么原因吗?您没有passwordEncoder的多个实现

    @Bean(name = "passwordEncoder")
      public PasswordEncoder passwordEncoder() {
            return new BCryptPasswordEncoder();
      }
    

    我认为spring在嘲笑这个实现时遇到了一个问题。相反,你可以

    @Bean
      public PasswordEncoder passwordEncoder() {
       return new BCryptPasswordEncoder();
      }
    

    它应该会起作用

  2. # 3 楼答案

    我通过简单地更改类注释解决了这个问题

    @WebMvcTest(EntryOverviewController.class)
    @Import(WebSecurityConfig.class)
    class EntryOverviewControllerTest {
    ...
    }
    

    所以我添加了@Import语句,它成功了