私は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メソッドが呼び出され、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.RELEASE
PDATE: Springバージョンを最新リリース4.0.3にアップグレードすると、同じgetUserService行で新しい例外が発生します。
org.springframework.context.support.GenericApplicationContext@3aa54263 has been closed already
この例外を修正する方法を教えてください。
テストクラスまたはテストメソッドに_@DirtiesContext
_で注釈を付けると、そのテストクラスまたはメソッドの後にApplicationContext
を閉じるようにSpringに指示します。したがって、後で閉じたコンテキストからBeanを取得しようとすると、表示されているような例外が発生します。
私の推測では、テストスイート内の他のテストクラスで_@DirtiesContext
_を使用しており、その結果、閉じたコンテキストへの参照を維持できる可能性があるため、SpringBeanFactory.setApplicationContext()
のロジックが壊れています。したがって、currentApplicationContext
を各テストに設定できるようにする必要があります。つまり、null
を削除します-次のようにチェックします
_public static void setApplicationContext(final ApplicationContext applicationContext) {
// always set the current context
SpringBeanFactory.applicationContext = applicationContext;
}
_
お役に立てれば!
-サム(Spring TestContext Frameworkの作成者)