Не определен bean-компонент с именем org.springframework.context.annotation.ConfigurationClassPostProcessor.importRegistry'

Я пытаюсь запустить полный пакет тестовых классов junit, и у меня есть классы аудита для моих классов домена следующим образом:

    @PrePersist
    public void prePersist(AuditableEntity e) {

      UserService userService = SpringBeanFactory.getBean(UserService.class);  
      // some auditing here  
    }

- класс SpringBeanFactory:

public class SpringBeanFactory {

    private static ApplicationContext applicationContext;

    public static <T> T getBean(final String name, final Class<T> requiredType) {
        T bean = null;
        if (applicationContext != null) {
            bean = applicationContext.getBean(name, requiredType);
        }
        return bean;
    }

    public static <T> T getBean(final Class<T> requiredType) {
        T bean = null;
        if (applicationContext != null) {
            bean = applicationContext.getBean(requiredType);
        }
        return bean;
    }

    public static void setApplicationContext(final ApplicationContext applicationContext) {
        if (SpringBeanFactory.applicationContext == null) {
            SpringBeanFactory.applicationContext = applicationContext;
        }
    }

}

Конфигурация класса тестирования:

@Autowired
private ApplicationContext applicationContext;

@Before
public void before() throws Exception {

    SpringBeanFactory.setApplicationContext(applicationContext);

}

-SpringTestingConfig класс:

@Configuration
@ComponentScan(basePackages = "com.myapp.data", excludeFilters = { @Filter(Configuration.class) })
@PropertySource("classpath:/test.properties")
@Profile("test")
public class SpringTestingConfig {

    private static Logger log = (Logger)LoggerFactory.getLogger(SpringTestingConfig.class);

    @Autowired
    private ApplicationContext applicationContext;

    @Bean
    public DataSource XdataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        if(log.isDebugEnabled()) log.debug("profile.name", "test");
        System.setProperty("profile.name", "test");

        dataSource.setDriverClassName("org.h2.Driver");
        String schemaName = ConfigurationUtil.config().getString("db.schema.name").toLowerCase();
        log.debug("SCHEMA IS " + schemaName);
        String url = "jdbc:h2:mem:test;MODE=Mysql;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;INIT=CREATE SCHEMA IF NOT EXISTS " +schemaName +"\\;" + "SET SCHEMA "+schemaName;
        dataSource.setUrl(url);
        //dataSource.setUrl("jdbc:h2:mem:test;MODE=Mysql;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;INIT=CREATE SCHEMA IF NOT EXISTS "    + schemaName);

        dataSource.setUsername("sa");

        //use your own local mysql in tests here...
//      dataSource.setDriverClassName("com.mysql.jdbc.Driver");
//      dataSource.setUrl("jdbc:mysql://localhost:3306/mv_tests?characterEncoding=UTF-8");
//      dataSource.setUsername("tomcat");
//      dataSource.setPassword("tomcat");
//        
        return dataSource;
    }

    @Bean
    public DataSource dataSource() {

        SpringBeanFactory.setApplicationContext(applicationContext);
        LoggerUtils.setAllApplicationLogs("DEBUG");
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        if(log.isDebugEnabled()) {
            log.debug("profile.name", "test");
        }
        System.setProperty("profile.name", "test");

        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        String schemaName = ConfigurationUtil.config().getString("db.schema.name");
        String username = ConfigurationUtil.config().getString("db.username");
        String password = ConfigurationUtil.config().getString("db.password");
        if( log.isDebugEnabled() ) {
            log.debug( "SCHEMA IS " + schemaName );
            log.debug( "Username IS " + username );
            log.debug( "Password IS " + password );
        }

        dataSource.setUrl("jdbc:mysql://localhost:3306/"+schemaName);
        dataSource.setUsername(username);
        dataSource.setPassword(password);

        return dataSource;
    }

}

-Тест класса аннотации:

@RunWith(SpringJUnit4ClassRunner.class)
@TestExecutionListeners({ WebContextTestExecutionListener.class, DependencyInjectionTestExecutionListener.class, DirtiesContextTestExecutionListener.class, TransactionalTestExecutionListener.class })
@ActiveProfiles("test")
@DirtiesContext
@ContextConfiguration(loader = AnnotationConfigContextLoader.class, classes = { SpringConfig.class, SpringTestingConfig.class, SpringLocalContainerJPAConfig.class, CustomConfiguration.class })
@Transactional

когда мой тестовый метод пытается сохранить сущность, он вызывает метод PrePersist, который, в свою очередь, вызывает метод получения Spring:

UserService userService = SpringBeanFactory.getBean(UserService.class);

который в свою очередь производит следующее исключение:

Error creating bean with name 'userService': 
Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: 
Could not autowire field: private com.motivosity.data.repository.UserRepository com.motivosity.service.impl.UserServiceImpl.userRepository; 
nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userRepositoryImpl': 
Injection of persistence dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: 
Error creating bean with name 'springLocalContainerJPAConfig': Injection of autowired dependencies failed; 
nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: 
javax.sql.DataSource com.motivosity.data.config.SpringLocalContainerJPAConfig.dataSource; 
nested exception is org.springframework.beans.factory.BeanCreationException: 
Error creating bean with name 'springTestingConfig': Initialization of bean failed; 
nested exception is org.springframework.beans.factory.BeanCreationException: 
Error creating bean with name 'org.springframework.cache.annotation.ProxyCachingConfiguration': 
Initialization of bean failed; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: 
No bean named 'org.springframework.context.annotation.ConfigurationClassPostProcessor.importRegistry' is defined

Я должен отметить, что это исключение возникает при запуске полного пакета тестовых классов, но при запуске этого тестового класса отдельно исключение не создается.

Кстати, я использую пружину 3.2.3.

ОБНОВЛЕНИЕ: когда я обновил весеннюю версию до последней версии 4.0.3, я получаю новое исключение в той же строке get UserService:

org.springframework.context.support.GenericApplicationContext@3aa54263 has been closed already

Посоветуйте, пожалуйста, как исправить это исключение.

1 ответ

Решение

Когда вы аннотируете тестовый класс или метод тестирования с @DirtiesContextВесной говоришь закрыть ApplicationContext после этого тестового класса или метода. Таким образом, если вы позже попытаетесь извлечь бин из закрытого контекста, вы получите исключение, которое вы видите.

Я думаю, что вы используете @DirtiesContext в других тестовых классах в вашем наборе тестов, и в результате логика в SpringBeanFactory.setApplicationContext() не работает, поскольку потенциально может поддерживать ссылку на закрытый контекст. Таким образом, вам нужно разрешить текущий ApplicationContext быть установленным для каждого теста. Другими словами, удалите null-проверьте, как следует

public static void setApplicationContext(final ApplicationContext applicationContext) {
    // always set the current context
    SpringBeanFactory.applicationContext = applicationContext;
}

Надеюсь это поможет!

- Сэм (автор Spring TestContext Framework)

Другие вопросы по тегам