JUnit测试中的SQLite数据库锁定

时间:2012-03-10 12:57:43

标签: java unit-testing sqlite junit

我在Eclipse 3.7上运行JUnit 4.10。我正在进行数据库测试:使用的数据库是带有sqlitejdbc的SQLite3。我尝试在windows和linux上运行测试,这是我的观察结果:

  • 在Windows 7 x64上,测试运行得更快(每次测试约0.6秒)。我收到有关“无法打开数据库文件”的错误。它们似乎是间歇性的(有时相同的测试可以在下次运行失败时通过一次)
  • 在Ubuntu 11.10 x64上,测试很慢(每次测试约3秒)。我收到有关“数据库锁定”的错误。与Windows的间歇性错误不同,此处错误似乎发生在同一个测试/文件中,一旦发生锁定错误,所有后续测试都会失败。

更新

您可以在GitHub找到测试代码。我认为问题可能与我的@BeforeClass@Before和测试套件的设置方式有关

我有一个类似

的测试套件
@RunWith(Suite.class)
@SuiteClasses({ DataAccessTests.class, SimpleQueryTests.class, ... })
public class DataAccessTestSuite {
    @BeforeClass
    public static void setUpDatabase() throws SQLException, ClassNotFoundException {    
        DataAccess.setEnvironment(DataAccess.DATABASE_TESTING);
        Connection conn = DataAccess.getConn();

        // truncate tables: simply DELETE statements
        truncateTables(conn);

        // insert test data, INSERT statements
        insertTestData(conn);
    }

然后在我的Test课程中,我有一个@Before也调用了设置。

public class EventsDataAccessTests {

    @Before
public void setup() throws SQLException, ClassNotFoundException {
    DataAccessTestSuite.setUpDatabase();
}

我在想我仍然想设置我的数据库,以防我不想调用整个套件。我认为问题与此有关,但我不确定它究竟是如何导致问题的。看来,即使我打电话给单个测试类,我的套件设置也会运行?或者如果没有,如果没有从套件调用测试,我如何确保它运行一次?

- 删除旧帖子 -

1 个答案:

答案 0 :(得分:2)

您需要确保一次只有一个线程尝试在sqlite数据库上进行写锁定。有关我的意思的概述,请阅读

(5) Can multiple applications or multiple instances of the same application access a single database file at the same time?

所以当你说:

  

如果我自己运行测试,它会通过。当试图运行整个   套房失败

我认为假设写锁不是由连接对象释放而另一个试图获取它是公平的。 因此,即使您不使用线程,也许GC在另一个测试创建另一个连接对象之前没有到达先前测试的连接对象。

也许您可以发布一些这些测试,以帮助更好地了解可能出现的问题。

<强>更新

你不应该在这里关闭连接吗?:

public static void tearDownDatabase() throws SQLException, ClassNotFoundException {
    Connection conn = DataAccess.getConn();
    truncateTables(conn);
}