如何在 Spring 中创建非事务性 JUnit 集成测试?
How to create non-transactional JUnit integration tests in Spring?
集成测试 class 注释为:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = IntegrationTestConfig.class)
它不应该在事务中 运行 所以 没有 标记为 @Transactional
但是我在尝试执行持久化时遇到错误, EntityManager
上的合并等操作,使用 @PersistenceContext
:
注入
No transactional EntityManager available
如何解决?
编辑:
根据评论中的要求,Spring 版本为 4.1。0.RELEASE 和 IntegrationTestConfig
如下:
@EnableAspectJAutoProxy
@EnableAsync
@EnableScheduling
@EnableTransactionManagement
@Configuration
public class IntegrationTestConfig {
/**
* Override the existing JPA data source bean with a test data source.
* @return test data source
*/
@Bean
public DataSource dataSource() {
final SimpleDriverDataSource dataSource = new SimpleDriverDataSource();
dataSource.setDriverClass(org.h2.Driver.class);
dataSource.setUrl("jdbc:h2:mem:test;MODE=MySQL;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;INIT=CREATE SCHEMA IF NOT EXISTS mydb");
dataSource.setUsername("sa");
dataSource.setPassword("");
return dataSource;
}
}
如果您确定永远不会调用 entityManager.flush()
,请按如下方式获取 PersistenceContext
:
@PersistenceContext(type = PersistenceContextType.EXTENDED)
private EntityManager entityManager;
为什么需要这个? Spring 数据JPA 手出来什么叫共享EntityManager
当@PersistenceContext
annotation is used (without any attributes). Full details for this are available in the JavaDocs for org.springframework.orm.jpa.SharedEntityManagerCreator
。此 class 维护查找 table,其中 EntityManager
方法 flush
、merge
、persist
、refresh
和 remove
必须在交易中 运行。因此,只要遇到不在事务内的方法调用,它就会退出。
注释 @PersistenceContext
有一个 type
属性,可以设置为 PersistenceContextType.EXTENDED
或 PersistenceContextType.TRANSACTION
之一,后者为默认值。因此,默认 @PersistenceContext
会导致 SharedEntityManagerCreator
查找事务并在找到 none 时退出。
使用 PersistenceContextType.EXTENDED
绕过了在获取 EntityManager
时检查交易的需要,因此代码应该可以工作。
flush
仍然无法在没有事务的情况下调用,因为 JPA 提供程序要求它只能在事务上下文中调用。
集成测试 class 注释为:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = IntegrationTestConfig.class)
它不应该在事务中 运行 所以 没有 标记为 @Transactional
但是我在尝试执行持久化时遇到错误, EntityManager
上的合并等操作,使用 @PersistenceContext
:
No transactional EntityManager available
如何解决?
编辑:
根据评论中的要求,Spring 版本为 4.1。0.RELEASE 和 IntegrationTestConfig
如下:
@EnableAspectJAutoProxy
@EnableAsync
@EnableScheduling
@EnableTransactionManagement
@Configuration
public class IntegrationTestConfig {
/**
* Override the existing JPA data source bean with a test data source.
* @return test data source
*/
@Bean
public DataSource dataSource() {
final SimpleDriverDataSource dataSource = new SimpleDriverDataSource();
dataSource.setDriverClass(org.h2.Driver.class);
dataSource.setUrl("jdbc:h2:mem:test;MODE=MySQL;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;INIT=CREATE SCHEMA IF NOT EXISTS mydb");
dataSource.setUsername("sa");
dataSource.setPassword("");
return dataSource;
}
}
如果您确定永远不会调用 entityManager.flush()
,请按如下方式获取 PersistenceContext
:
@PersistenceContext(type = PersistenceContextType.EXTENDED)
private EntityManager entityManager;
为什么需要这个? Spring 数据JPA 手出来什么叫共享EntityManager
当@PersistenceContext
annotation is used (without any attributes). Full details for this are available in the JavaDocs for org.springframework.orm.jpa.SharedEntityManagerCreator
。此 class 维护查找 table,其中 EntityManager
方法 flush
、merge
、persist
、refresh
和 remove
必须在交易中 运行。因此,只要遇到不在事务内的方法调用,它就会退出。
注释 @PersistenceContext
有一个 type
属性,可以设置为 PersistenceContextType.EXTENDED
或 PersistenceContextType.TRANSACTION
之一,后者为默认值。因此,默认 @PersistenceContext
会导致 SharedEntityManagerCreator
查找事务并在找到 none 时退出。
使用 PersistenceContextType.EXTENDED
绕过了在获取 EntityManager
时检查交易的需要,因此代码应该可以工作。
flush
仍然无法在没有事务的情况下调用,因为 JPA 提供程序要求它只能在事务上下文中调用。