数据库单元测试框架?

Sma*_*ion 7 java spring dbunit unit-testing jpa

在我的项目中,我使用了spring,jpa和PostgreSQL DB,我在DB中有很多表,我需要对所有这些表进行单元测试.

是否有任何框架在每次测试完成后回滚所有事务,因此每个测试都会有新的/相同的DB数据进行测试.这种方式在所有测试执行之后,DB模式的数据将保持原样.

有什么建议吗?

我对DBUnit有所了解,但是我需要为每个测试编写每个输入数据的.xml文件,需要在setup()中插入数据并清除/删除tearDown()中的数据,但似乎没有更好的策略对我来说.

任何建议表示赞赏.谢谢.

Vin*_*lds 3

是否有任何框架在每次测试完成后回滚所有事务,以便每个测试都将有新鲜/相同的数据库数据进行测试。这样在所有测试执行之后,数据库模式的数据将保持原样。

从我当天早些时候发布的其他答案来看,是的,使用 DbUnit 可以做到这一点。(根据您的编辑,您不需要这个;我的答案的后续部分说明了我使用 DbUnit 的原因以及何时不使用它)。

以下代码片段演示了如何执行每个测试的设置:

@Before
public void setUp() throws Exception
{
    logger.info("Performing the setup of test {}", testName.getMethodName());
    IDatabaseConnection connection = null;
    try
    {
        connection = getConnection();
        IDataSet dataSet = getDataSet();
        //The following line cleans up all DbUnit recognized tables and inserts and test data before every test.
        DatabaseOperation.CLEAN_INSERT.execute(connection, dataSet);
    }
    finally
    {
        // Closes the connection as the persistence layer gets it's connection from elsewhere
        connection.close();
    }
}

private IDatabaseConnection getConnection() throws Exception
{
    @SuppressWarnings({ "rawtypes", "unused" })
    Class driverClass = Class.forName("org.apache.derby.jdbc.ClientDriver");
    Connection jdbcConnection = DriverManager.getConnection(jdbcURL, "XXX",
            "YYY");
    IDatabaseConnection databaseConnection = new DatabaseConnection(jdbcConnection);
    return databaseConnection;
}

private IDataSet getDataSet() throws Exception
{
    ClassLoader classLoader = this.getClass().getClassLoader();
    return new FlatXmlDataSetBuilder().build(classLoader.getResourceAsStream("database-test-setup.xml"));
}
Run Code Online (Sandbox Code Playgroud)

database-test-setup.xml文件包含每次测试将插入数据库的数据。DatabaseOperation.CLEAN_INSERT该方法中的使用setup可确保文件中指定的所有表都将被清除(通过删除所有行),然后在测试数据文件中插入指定的数据。

避免 DbUnit

我专门使用上述方法在每次测试开始之前清除序列,因为应用程序使用 JPA 提供程序在单独的事务中更新序列。如果您的应用程序没有执行类似的操作,那么您可以简单地在您的setup()方法中启动一个事务,并在测试后在拆卸时发出回滚。如果我的应用程序不使用序列(并且如果我不想重置它们),那么我的设置例程将非常简单:

@Before
public void setUp() throws Exception
{
    logger.info("Performing the setup of test {}", testName.getMethodName());
    // emf is created in the @BeforeClass annotated method
    em = emf.createEntityManager();
    // Starts the transaction before every test
    em.getTransaction.begin();
}

@After
public void tearDown() throws Exception
{
    logger.info("Performing the teardown of test {}", testName.getMethodName());
    if (em != null)
    {
        // Rolls back the transaction after every test
        em.getTransaction().rollback();
        em.close();
    }
}
Run Code Online (Sandbox Code Playgroud)

另外,我将dbdeploy与 Maven 结合使用,但这主要是为了使测试数据库与版本化数据模型保持最新。