Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何测试spring配置类?_Java_Spring_Spring Mvc_Junit - Fatal编程技术网

Java 如何测试spring配置类?

Java 如何测试spring配置类?,java,spring,spring-mvc,junit,Java,Spring,Spring Mvc,Junit,我有一个spring应用程序,其中配置类是bean的实例 申请类别: @Configuration @EnableAspectJAutoProxy @EnableSpringDataWebSupport @EnableTransactionManagement @ComponentScan(basePackageClasses = Application.class) @PropertySource(value = {"classpath:foo.properties"}) @EnableJpa

我有一个spring应用程序,其中配置类是bean的实例

申请类别:

@Configuration
@EnableAspectJAutoProxy
@EnableSpringDataWebSupport
@EnableTransactionManagement
@ComponentScan(basePackageClasses = Application.class)
@PropertySource(value = {"classpath:foo.properties"})
@EnableJpaRepositories(basePackageClasses = Application.class)
@EnableJpaAuditing
public class Application {

    @Inject
    private Environment env;

    @Bean
    JndiTemplate jndiTemplate() {
        return new JndiTemplate();
    }

    @Bean
    public DataSource dataSource() {        
        DataSource dataSource = getDataSource();
        if (dataSource == null) {
            dataSource = new BasicDataSource();
            ((BasicDataSource) dataSource).setUsername(env.getProperty("jdbc.user"));
            ((BasicDataSource) dataSource).setPassword(env.getProperty("jdbc.password""));

            ((BasicDataSource) dataSource).setDriverClassName(env.getProperty("jdbc.driverClassName"));
            ((BasicDataSource) dataSource).setUrl(env.getProperty("jdbc.url"));
        }
        return dataSource;
    }

    @Bean
    public PlatformTransactionManager transactionManager() {
        EntityManagerFactory factory = entityManagerFactory().getObject();
        return new JpaTransactionManager(factory);
    }

    //....
}
@Configuration
@ComponentScan(basePackageClasses = Application.class, includeFilters = @Filter({Controller.class, Component.class}), useDefaultFilters = true)
class MvcConfiguration extends WebMvcConfigurationSupport {
    private static final String MESSAGES = "classpath:/i18n";

    private static final String VIEW_PREFIX = "/WEB-INF/views/";

    @Inject
    private Environment env;

    @Override
    public RequestMappingHandlerMapping requestMappingHandlerMapping() {
        RequestMappingHandlerMapping requestMappingHandlerMapping = super.requestMappingHandlerMapping();
        requestMappingHandlerMapping.setUseSuffixPatternMatch(false);
        requestMappingHandlerMapping.setUseTrailingSlashMatch(true);

        return requestMappingHandlerMapping;
    }

    @Bean(name = "messageSource")
    public MessageSource messageSource() {
        ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
        messageSource.setBasename(MESSAGES);
        messageSource.setCacheSeconds(5);

        return messageSource;
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/static/").addResourceLocations("/static/**");
    }

    @Bean
    public MultipartResolver filterMultipartResolver(){
        CommonsMultipartResolver resolver = new CommonsMultipartResolver();
        resolver.setMaxUploadSize(Long.parseLong(env.getProperty("multipart.max.size")));
        return resolver;
    }

    //....

}
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
class SecurityConfiguration extends WebSecurityConfigurerAdapter {

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


    //....

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //Logout por POST con el valor de token csrf
        http.authorizeRequests()
                .antMatchers("/static/**").permitAll()
                .anyRequest().authenticated()
                .and()
            .formLogin()
                .loginPage("/login")
                .permitAll()
                .failureUrl("/login?error=1")
                .loginProcessingUrl("/authenticate")
                .and()
            .logout()
                .logoutUrl("/logout")
                .logoutSuccessUrl("/signin")
                .permitAll();
    }

}
MVC配置类:

@Configuration
@EnableAspectJAutoProxy
@EnableSpringDataWebSupport
@EnableTransactionManagement
@ComponentScan(basePackageClasses = Application.class)
@PropertySource(value = {"classpath:foo.properties"})
@EnableJpaRepositories(basePackageClasses = Application.class)
@EnableJpaAuditing
public class Application {

    @Inject
    private Environment env;

    @Bean
    JndiTemplate jndiTemplate() {
        return new JndiTemplate();
    }

    @Bean
    public DataSource dataSource() {        
        DataSource dataSource = getDataSource();
        if (dataSource == null) {
            dataSource = new BasicDataSource();
            ((BasicDataSource) dataSource).setUsername(env.getProperty("jdbc.user"));
            ((BasicDataSource) dataSource).setPassword(env.getProperty("jdbc.password""));

            ((BasicDataSource) dataSource).setDriverClassName(env.getProperty("jdbc.driverClassName"));
            ((BasicDataSource) dataSource).setUrl(env.getProperty("jdbc.url"));
        }
        return dataSource;
    }

    @Bean
    public PlatformTransactionManager transactionManager() {
        EntityManagerFactory factory = entityManagerFactory().getObject();
        return new JpaTransactionManager(factory);
    }

    //....
}
@Configuration
@ComponentScan(basePackageClasses = Application.class, includeFilters = @Filter({Controller.class, Component.class}), useDefaultFilters = true)
class MvcConfiguration extends WebMvcConfigurationSupport {
    private static final String MESSAGES = "classpath:/i18n";

    private static final String VIEW_PREFIX = "/WEB-INF/views/";

    @Inject
    private Environment env;

    @Override
    public RequestMappingHandlerMapping requestMappingHandlerMapping() {
        RequestMappingHandlerMapping requestMappingHandlerMapping = super.requestMappingHandlerMapping();
        requestMappingHandlerMapping.setUseSuffixPatternMatch(false);
        requestMappingHandlerMapping.setUseTrailingSlashMatch(true);

        return requestMappingHandlerMapping;
    }

    @Bean(name = "messageSource")
    public MessageSource messageSource() {
        ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
        messageSource.setBasename(MESSAGES);
        messageSource.setCacheSeconds(5);

        return messageSource;
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/static/").addResourceLocations("/static/**");
    }

    @Bean
    public MultipartResolver filterMultipartResolver(){
        CommonsMultipartResolver resolver = new CommonsMultipartResolver();
        resolver.setMaxUploadSize(Long.parseLong(env.getProperty("multipart.max.size")));
        return resolver;
    }

    //....

}
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
class SecurityConfiguration extends WebSecurityConfigurerAdapter {

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


    //....

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //Logout por POST con el valor de token csrf
        http.authorizeRequests()
                .antMatchers("/static/**").permitAll()
                .anyRequest().authenticated()
                .and()
            .formLogin()
                .loginPage("/login")
                .permitAll()
                .failureUrl("/login?error=1")
                .loginProcessingUrl("/authenticate")
                .and()
            .logout()
                .logoutUrl("/logout")
                .logoutSuccessUrl("/signin")
                .permitAll();
    }

}
和SecurityConfiguration类别:

@Configuration
@EnableAspectJAutoProxy
@EnableSpringDataWebSupport
@EnableTransactionManagement
@ComponentScan(basePackageClasses = Application.class)
@PropertySource(value = {"classpath:foo.properties"})
@EnableJpaRepositories(basePackageClasses = Application.class)
@EnableJpaAuditing
public class Application {

    @Inject
    private Environment env;

    @Bean
    JndiTemplate jndiTemplate() {
        return new JndiTemplate();
    }

    @Bean
    public DataSource dataSource() {        
        DataSource dataSource = getDataSource();
        if (dataSource == null) {
            dataSource = new BasicDataSource();
            ((BasicDataSource) dataSource).setUsername(env.getProperty("jdbc.user"));
            ((BasicDataSource) dataSource).setPassword(env.getProperty("jdbc.password""));

            ((BasicDataSource) dataSource).setDriverClassName(env.getProperty("jdbc.driverClassName"));
            ((BasicDataSource) dataSource).setUrl(env.getProperty("jdbc.url"));
        }
        return dataSource;
    }

    @Bean
    public PlatformTransactionManager transactionManager() {
        EntityManagerFactory factory = entityManagerFactory().getObject();
        return new JpaTransactionManager(factory);
    }

    //....
}
@Configuration
@ComponentScan(basePackageClasses = Application.class, includeFilters = @Filter({Controller.class, Component.class}), useDefaultFilters = true)
class MvcConfiguration extends WebMvcConfigurationSupport {
    private static final String MESSAGES = "classpath:/i18n";

    private static final String VIEW_PREFIX = "/WEB-INF/views/";

    @Inject
    private Environment env;

    @Override
    public RequestMappingHandlerMapping requestMappingHandlerMapping() {
        RequestMappingHandlerMapping requestMappingHandlerMapping = super.requestMappingHandlerMapping();
        requestMappingHandlerMapping.setUseSuffixPatternMatch(false);
        requestMappingHandlerMapping.setUseTrailingSlashMatch(true);

        return requestMappingHandlerMapping;
    }

    @Bean(name = "messageSource")
    public MessageSource messageSource() {
        ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
        messageSource.setBasename(MESSAGES);
        messageSource.setCacheSeconds(5);

        return messageSource;
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/static/").addResourceLocations("/static/**");
    }

    @Bean
    public MultipartResolver filterMultipartResolver(){
        CommonsMultipartResolver resolver = new CommonsMultipartResolver();
        resolver.setMaxUploadSize(Long.parseLong(env.getProperty("multipart.max.size")));
        return resolver;
    }

    //....

}
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
class SecurityConfiguration extends WebSecurityConfigurerAdapter {

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


    //....

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //Logout por POST con el valor de token csrf
        http.authorizeRequests()
                .antMatchers("/static/**").permitAll()
                .anyRequest().authenticated()
                .and()
            .formLogin()
                .loginPage("/login")
                .permitAll()
                .failureUrl("/login?error=1")
                .loginProcessingUrl("/authenticate")
                .and()
            .logout()
                .logoutUrl("/logout")
                .logoutSuccessUrl("/signin")
                .permitAll();
    }

}

如何使用JUnit测试它们?如何测试在spring上下文中创建的bean?

我相信这只能通过集成测试来实现

单元测试的目的不是检查是否成功创建了整个Spring上下文

您可以通过使用mock等进行单元测试来测试每个配置方法,以检查它们是否正常,但整个Spring上下文是一个集成测试

我通常通过执行Spring文档所称的“Spring单元测试”(对我来说更像是控制器+视图的集成测试)来进行配置测试

其思想是,如果您可以让Spring上下文运行控制器集成测试,那么您的配置就可以了

spring文档中有整整一章介绍了如何进行这种测试。

您可以在JUnit测试中构建上下文,前提是所有bean都可以在测试环境中实例化。您可以使用及其
scan()
方法来执行此操作

这样的测试应该足以快速验证配置。您可以从那里开始,从上下文中获取bean以进行更复杂的测试

两个陷阱:

  • 可能对惰性初始化bean不起作用
    • 对于此类类,您可能需要使用
      getBean()
      从上下文中实际请求一个实例,以确保它被创建—您可以通过这种方式测试这种期望
  • 可能并不总是可能的,例如,如果您有一些数据库连接作为依赖项,并且在测试环境中没有访问数据库的权限
    • 出于测试的目的,您可能需要模拟这些bean
一句话——“不要”,那样会产生疯狂

您真正想要的是更高级别的测试,这些测试使用您的Spring配置,但仍然关注行为而不是实现

例如,查看您的安全配置—您并不真正关心是否调用了
configure
方法,也不关心它的作用,您想要测试的是:

  • 静态页面不需要身份验证
  • 其他页面确实需要身份验证
  • 登录工作
  • 注销工程

  • 将Spring用于DI和安全性只是这些东西的实现方式,而您的测试应该关注这些东西实际工作的事实。

    您应该能够使用@ContextConfiguration注释测试配置。例如,SecurityConfiguration类可以这样测试:

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(classes = SecurityConfiguration.class) 
    class SecurityConfigurationTest {
    
        @Autowired
        SecurityConfiguration securityConfiguration;
    
        @Test
        public void passwordEncoderTest() throws Exception {
            final BCryptPasswordEncoder encoder = securityConfiguration.passwordEncoder();
            final String encodedPassword = encoder.encode("password");
            assertNotNull(encodedPassword);
        }
    }
    

    对于基本bean测试和一些高级属性配置,我使用
    ApplicationContextRunner()
    来测试这些类

    对于springsecurity@Configuration类,我将加载该类,然后定义一个控制器,以查看是否正确定义了该类上的安全性