最終編集:問題の解決策を見つけました(質問の下部にあります)。
私は悲しみを引き起こしているNunitの問題を抱えています。編集:実際にはSQLiteの問題のように見えますが、まだ100%確実ではありません。
私のTestFixtureには、各テストでSQLiteデータベースとして使用されるランダムなファイル名を生成する設定があります。
[Setup]
public void Setup()
{
// "filename" is a private field in my TestFixture class
filename = ...; // generate random filename
}
私の各テストでは、データベースにアクセスする各メソッドでこの構成を使用しています。
[Test]
public void TestMethod()
{
using (var connection = Connect())
{
// do database activity using connection
// I've tried including this line but it doesn't help
// and is strictly unnecessary:
connection.Close();
}
}
private DbConnection Connect()
{
var connection = DbProviderFactories.GetFactory("System.Data.SQLite").CreateConnection();
connection.ConnectionString = "Data Source=" + filename;
connection.Open();
return connection;
}
そのため、1つのヘルパーメソッドConnect()
がすべてのメソッドで使用されます。using() { }
コンストラクトがDispose()
最後に接続を呼び出しTestMethod()
、SQLiteデータベースファイルへの接続を解放していると想定しています。
私が抱えている問題は、[TearDown]メソッドにあります。
[TearDown]
public void Cleanup()
{
File.Delete(filename); // throws an IOException!
}
すべてのテストで例外が発生します。
System.IO.IOException: The process cannot access the file 'testdatabase2008-12-17_1030-04.614065.sqlite' because it is being used by another process.
[TearDown]に到達すると、すべてのテストが失敗するため、一時的なデータベースファイル(テストごとに1つ、それぞれ異なる名前)でいっぱいのディレクトリと、失敗したテストがたくさんあります。
どのプロセスがファイルにアクセスしていますか?2番目のプロセスがファイルにアクセスする方法がわかりません。はconnection
完全にスコープ外になり、ファイルを削除しようとしている時点でDispose()されているため、SQLiteに関連するものにすることはできません。それをできる?
すべてのテストを実行した場合、または1つのテストだけを実行した場合でも、同じ結果が得られることに注意してください。
更新:それで、DbCommandオブジェクトのDispose()も試していませんでした(DbConnectionをDispose()する他のすべてのADO.NETプロバイダーもその接続上のコマンドをDispose()すると仮定しました) 。)これで、次のようになります。
[Test]
public void TestMethod()
{
using (var connection = Connect())
{
using (var command = connection.CreateCommand())
{
// do database activity using connection
}
}
}
違いはありませんでした。File.Delete()行は引き続きIOExceptionをスローします。:-(
[TearDown]でその1行を削除すると、すべてのテストに合格しますが、大量の一時データベースファイルが残ります。
別の更新: これは問題なく機能します:
var filename = "testfile.sqlite";
using (var connection = BbProviderFactories.GetFactory("System.Data.SQLite").CreateConnection())
{
connection.ConnectionString = "Data Source=" + filename;
connection.Open();
var createCommand = connection.CreateCommand();
createCommand.CommandText =
"CREATE TABLE foo (id integer not null primary key autoincrement, bar text not null);";
createCommand.ExecuteNonQuery();
var insertCommand = connection.CreateCommand();
insertCommand.CommandText = "INSERT INTO foo (bar) VALUES (@bar)";
insertCommand.Parameters.Add(insertCommand.CreateParameter());
insertCommand.Parameters[0].ParameterName = "@bar";
insertCommand.Parameters[0].Value = "quux";
insertCommand.ExecuteNonQuery();
}
File.Delete(filename);
理解できない!
更新:解決策が見つかりました:
[TearDown]
public void Cleanup()
{
GC.Collect();
File.Delete(filename);
}
デバッガーを介して単体テストを実行しましたが、[TearDown]
メソッドが開始されると、SQLiteDbConnectionへの参照はなくなりました。ただし、GCを強制するとそれらをクリーンアップする必要があります。SQLiteにバグがあるはずです。