编写单元测试时,我需要知道什么才能访问数据库(通过JPA + Hibernate),以便它们可以并行运行?我们开始使用mavens并行单元测试功能和经验测试失败,当它们在单个线程中运行时不会发生。
我将简要介绍一下我们现在正在编写测试的方法。我们在EntityManager
中设置@Before
和其他类,开始事务并最终插入测试数据,我们在类中的所有测试都需要测试数据(在测试中创建测试特定数据)。 @After
运行测试,我们通过调用Transaction.rollback();
和null
所有成员变量来回滚所有内容。
我们针对内存中的hsqldb运行所有单元测试。
public class TestLogEntryDAO {
private EntityManager em;
private LogEntryDAO dao;
@Before
public void before() {
em = Persistence.createEntityManagerFactory("junit")
.createEntityManager();
dao = new DAOFactory<LogEntryDAO>(LogEntryDAO.class).newInstance(em,
Mockito.mock(ILogger.class));
em.getTransaction().begin();
RecordDAO recordDAO = new DAOFactory<RecordDAO>(RecordDAO.class)
.newInstance(em, Mockito.mock(ILogger.class));
recordDAO.setLogEntryDAO(dao);
createTestData(); // Is this ok?
}
@After
public void after() {
em.getTransaction().rollback();
em = null;
dao = null;
}
@Test
public void testSomething() {
// ...
}
}
提前致谢!
答案 0 :(得分:1)
如果满足以下一个或多个条件,涉及JPA的并行测试必然会失败:
如果需要运行并行测试,可以将读取数据的所有测试组合到一个单独的套件中,但这仍然需要序列化可以改变数据库状态的测试。如果您的测试允许,您可以为并行运行的每个测试使用单独的数据集;请注意,并非所有应用程序和所有测试都适用。
特定于测试的数据集可以从文件集(例如,使用DbUnit)或内存数据集(使用自定义测试值工厂准备)加载,每个并行测试依赖于不同的项目集合。很明显,任何公共数据都不能在测试中进行变异,否则最终将回滚事务(如果存在乐观锁定),或者测试将失败。
此外,不得跨测试共享跨测试可变异的数据。如果对每个测试使用不同的引脚值,这很容易实现。您需要确保测试将断言这些值或特定于测试的等效不变属性。可以使用thread-id执行数据固定。
为了提供上述示例,如果您正在运行将在数据库中保留实体A(具有属性A1和A2)的测试,则测试T1必须保留A的实例,其值为A1 = x1且A2 = y1和并行测试T2必须保持A的另一个实体,其值为A1 = x2和A2 = y2。这假设并行运行的其他测试将改变A1和A2的值。如果你的测试具有不改变A1的特性,那么A1的所有这些值在测试中都是恒定的。