2

我正在为我的 Spring 3.2.8 + Hibernate 4.3.4 应用程序编写一些 junit 测试。我的测试类注释为:

@DirtiesContext(classMode=ClassMode.AFTER_EACH_TEST_METHOD)
@Transactional
public class UserServiceImplTest {
   ...
   ...
}

但是,尝试使用实体管理器的方面会引发以下错误:

org.springframework.dao.InvalidDataAccessApiUsageException: EntityManagerFactory is closed; nested exception is java.lang.IllegalStateException: EntityManagerFactory is closed

如果查看日志,我会在第二次测试开始时看到以下错误消息:

2014-04-02 16:36:48,891 [main] WARN  org.hibernate.jpa.internal.EntityManagerFactoryRegistry - HHH000436: Entity manager factory name (default) is already registered.  If entity manager will be clustered or passivated, specify a unique value for property 'hibernate.ejb.entitymanager_factory_name'

我意识到这只是一个警告,但我想知道这是否是问题的一部分。我不明白为什么在@DirtiesContext应该确保在开始第二次测试之前清除上下文时抱怨工厂已经注册。

我确实看到在第一次测试结束时正在清理上下文:

2014-04-02 16:36:10,733 [main] INFO  springframework.test.context.transaction.TransactionalTestExecutionListener - Rolled back transaction after test execution for test context [TestContext@1ff221ad testClass = UserServiceImplTest, testInstance = com.ia.service.UserServiceImplTest@5180f53d, testMethod = testUpdateRoles@UserServiceImplTest, testException = [null], mergedContextConfiguration = [WebMergedContextConfiguration@6964a198 testClass = UserServiceImplTest, locations = '{classpath:META-INF/spring/applicationContext*.xml}', classes = '{}', contextInitializerClasses = '[]', activeProfiles = '{test}', resourceBasePath = 'src/main/webapp', contextLoader = 'org.springframework.test.context.web.WebDelegatingSmartContextLoader', parent = [null]]]
2014-04-02 16:36:10,735 [main] INFO  springframework.web.context.support.GenericWebApplicationContext - Closing org.springframework.web.context.support.GenericWebApplicationContext@53c3dcdc: startup date [Wed Apr 02 16:35:00 EDT 2014]; root of context hierarchy
2014-04-02 16:36:10,736 [main] INFO  springframework.beans.factory.support.DefaultListableBeanFactory - Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@2ff0a910: defining beans [dataSource,entityManagerFactory,org.springframework.transaction.config.internalTransactionAspect,hibernateJpaVendorAdapter,transactionManager,org.springframework.data.repository.core.support.RepositoryInterfaceAwareBeanPostProcessor#0,org.springframework.data.jpa.repository.support.EntityManagerBeanDefinitionRegistrarPostProcessor#0,org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor#0,rateRepository,userRepositoryImpl,userRepository,patchRepository,org.springframework.security.filterChains,org.springframework.security.filterChainProxy,org.springframework.security.web.DefaultSecurityFilterChain#0,org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler#0,org.springframework.security.access.method.DelegatingMethodSecurityMetadataSource#0,org.springframework.security.access.vote.AffirmativeBased#0,org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor#0,org.springframework.security.methodSecurityMetadataSourceAdvisor,org.springframework.aop.config.internalAutoProxyCreator,org.springframework.security.web.PortMapperImpl#0,org.springframework.security.web.PortResolverImpl#0,org.springframework.security.config.authentication.AuthenticationManagerFactoryBean#0,org.springframework.security.authentication.ProviderManager#0,org.springframework.security.web.context.NullSecurityContextRepository#0,org.springframework.security.web.savedrequest.NullRequestCache#0,org.springframework.security.access.vote.AffirmativeBased#1,org.springframework.security.web.access.intercept.FilterSecurityInterceptor#0,org.springframework.security.web.access.DefaultWebInvocationPrivilegeEvaluator#0,org.springframework.security.authentication.AnonymousAuthenticationProvider#0,org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint#0,org.springframework.security.userDetailsServiceFactory,org.springframework.security.web.DefaultSecurityFilterChain#1,org.springframework.security.authentication.dao.DaoAuthenticationProvider#0,org.springframework.security.authentication.DefaultAuthenticationEventPublisher#0,org.springframework.security.authenticationManager,basicAuthenticationFilter,authenticationEntryPoint,defaultWebSecurityExpressionHandler,org.springframework.context.support.PropertySourcesPlaceholderConfigurer#0,org.springframework.context.config.internalBeanConfigurerAspect,contactDataOnDemand,userDataOnDemand,testBase.BeanRegistry,securityService,patchServiceImpl,rateServiceImpl,userServiceImpl,appConfig,viewConfig,webContextFilter,patchEngineContextListener,patchEngineImpl.PatchEngineInitializer,patchEngineImpl,initializeUsersRolesAndPermissionsPatch,tilesContainerFactory,viewMetaPreparer,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.annotation.internalPersistenceAnnotationProcessor,applicationProperties,org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor,org.springframework.data.auditing.AuditingHandler#0,org.springframework.data.jpa.domain.support.AuditingEntityListener,org.springframework.data.jpa.domain.support.AuditingBeanFactoryPostProcessor,org.springframework.data.auditing.AuditingHandler#1,auditorProvider,objectMapper,org.springframework.orm.jpa.SharedEntityManagerCreator#0]; root of factory hierarchy
2014-04-02 16:36:10,754 [main] INFO  org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean - Closing JPA EntityManagerFactory for persistence unit 'default'

所以我不确定为什么它抱怨 EntityManagerFactory 已经注册。此外,我不确定为什么在尝试访问 EMF 时它会关闭。

我是否需要做一些特别的事情来确保它在每次测试中仍然可以访问?我确实在 SO 上找到了与该问题相关的帖子,但并不能帮助我确定发生这种情况的原因。

4

2 回答 2

2

It turns out after much debugging that the problem is in the aspect that is using the EntityManagerFactory. Given that the aspect is instantiated outside the Spring context, when the context is refreshed, the aspect's references are not updated. Consequently, the aspect is holding a reference to an EMF that is indeed closed - the original EMF from the first unit test. Now I just have to figure out how to get Spring to update/refresh the references when the context is updated.

于 2014-04-03T01:50:48.000 回答
1

似乎有些东西试图在设置弹簧上下文之前或处理它之后获得持久性上下文。

你没有一些访问持久性的junit @before 或@after 注释方法吗?

于 2014-04-02T21:08:39.800 回答