在测试用例之后使用SQL回滚,但正在测试的方法使用commit

时间:2014-06-26 16:02:39

标签: java postgresql jdbc junit automated-tests

我正在尝试为我们的某个应用程序的数据库访问方法编写单元测试。我们有一个专用的测试数据库(实时数据库的定期转储/复制)。通常,每个测试用例都在一个事务中运行,然后回滚。我们在测试用例之前使用Connection.setAutoCommit(false),之后使用Connection.rollback()来完成此操作。

但这一次,我试图为一个方法编写一个测试,该方法本身就是一个事务,并在最后使用Connection.commit()

有没有办法让commit实际提交到数据库而不会在被测试的方法中引发错误?也就是说,我怎样才能让这个测试用例真正改变测试数据库的内容?

注意:使用Java,JDBC和Junit。 java.sql.Connection用于数据库连接,java.sql.PreparedStatement用于运行查询。

@Before和@After代码:

/**
 * Obtain a new connection and set autoCommit to false.
 * This lets us run a test case then revert all of the changes
 * so the test cases don't interfere with each other.
 */
@Before
public void initConnection() {
    conn = Database.getConnection();
    try {
        conn.setAutoCommit(false);
    } catch (SQLException e) {
        e.printStackTrace();
        fail("Unable to set connection AutoCommit=false");
    }
}

/**
 * Rollback the changes made by the test case
 * and close the connection.
 */
@After
public void rollbackConnection() {
    try {
        conn.rollback();
    } catch (SQLException e) {
        e.printStackTrace();
        fail("Unable to rollback");
    }
    Database.closeConnection(conn);
}

2 个答案:

答案 0 :(得分:1)

你为什么要这样做?如果您正在编写正确的测试,那么您可能希望验证数据确实已经提交并符合您尝试完成的任何操作。如果您担心这些变化,请在完成后进行清理。

但是,如果确实存在合理的原因,则可以删除事务(txn)代码,编写辅助函数,将函数调用包装在事务中,让客户端调用该辅助函数,测试代码调用原始函数。这可能不是最好的方法,但可以选择。

答案 1 :(得分:0)

问我的办公室伙伴是否有任何想法。有人建议嘲笑它(使用Mockquito),这让我有了更好的选择。我正在为Connection创建一个扩展Connection的包装器,其行为与正常连接类似,但是当使用与事务相关的方法时,它的行为方式不同。

在生产中,使用正常的Connection,对于测试用例,将使用此包装类。

具体做法是:

  • 当它在每个测试用例的开头实例化时,它会启动一个真实的事务。
  • 当被告知将autocommit设置为false(通常是我们如何开始一个长事务)时,它会创建一个Savepoint并保持它
  • 当它被告知要提交时,它会释放旧的Savepoint并获得一个新的。{/ li>
  • 当它被告知回滚时,它会回滚到Savepoint
  • 当autocommit设置为false时将其设置为true会释放Savepoint
  • 如果被告知要设置Savepoint(如果没有进行则应该启动交易),除了设置请求的Savepoint之外,它还会启动上述虚假交易。< / LI>
  • 在测试用例结束时,将回滚真实交易。

这些更改允许它在它正在测试的使用事务的方法的事务中表现得像它在测试用例结束后保持整个事物可以恢复。

PS - 如果有什么我应该做但不是,请告诉我,以便我可以改进包装类。