如何针对可以并行运行的JPA编写junit测试?

时间:2011-08-09 18:05:38

标签: java jpa junit jpa-2.0 parallel-processing

编写单元测试时,我需要知道什么才能访问数据库(通过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() {
        // ...
    }
}

提前致谢!

1 个答案:

答案 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的所有这些值在测试中都是恒定的。