Ste*_*son 18 sqlite nunit unit-testing ioexception
最终编辑:我找到了问题的解决方案(在问题的底部).
我有一个让你感到悲伤的Nunit问题.编辑:实际上它看起来更像是一个SQLite问题,但我还不是100%肯定.
我的TestFixture有一个设置,可以生成一个随机文件名,在我的每个测试中都用作SQLite数据库.
[Setup]
public void Setup()
{
// "filename" is a private field in my TestFixture class
filename = ...; // generate random filename
}
Run Code Online (Sandbox Code Playgroud)
我的每个测试都在访问数据库的每个方法中使用此构造:
[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;
}
Run Code Online (Sandbox Code Playgroud)
因此Connect()所有方法都使用了一个辅助方法.我假设using() { }构造Dispose()在结束时调用连接TestMethod()并释放与SQLite数据库文件的连接.
我遇到的问题是我的[TearDown]方法:
[TearDown]
public void Cleanup()
{
File.Delete(filename); // throws an IOException!
}
Run Code Online (Sandbox Code Playgroud)
每次测试我都会得到一个例外:
System.IO.IOException: The process cannot access the file 'testdatabase2008-12-17_1030-04.614065.sqlite' because it is being used by another process.
Run Code Online (Sandbox Code Playgroud)
当他们到达[TearDown]时,所有测试都失败了,所以我最终得到一个充满临时数据库文件的目录(每个测试一个,每个都有不同的名称)和一大堆失败的测试.
访问文件的过程是什么?我不知道第二个进程如何访问该文件.在connection我尝试删除文件的时候,已经完全超出了范围并且已经是Dispose()d,因此它不能与SQLite相关.它可以?
请注意,如果我运行所有测试或只进行一次测试,我会得到相同的结果.
更新:所以我也试过Dispose()我的DbCommand对象,因为我没有这样做(我假设Dispose()DbConnection的所有其他ADO.NET提供程序也Dispose()s在该连接上的任何命令.)现在他们看起来像:
[Test]
public void TestMethod()
{
using (var connection = Connect())
{
using (var command = connection.CreateCommand())
{
// do database activity using connection
}
}
}
Run Code Online (Sandbox Code Playgroud)
它没有任何区别 - File.Delete()行仍然抛出IOException.:-(
如果我在[TearDown]中删除那一行,那么我的所有测试都会通过,但是我留下了一大堆临时数据库文件.
另一个更新: 这很好用:
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);
Run Code Online (Sandbox Code Playgroud)
我不明白!
更新:找到解决方案:
[TearDown]
public void Cleanup()
{
GC.Collect();
File.Delete(filename);
}
Run Code Online (Sandbox Code Playgroud)
我通过调试器运行了单元测试,当[TearDown]方法启动时,肯定没有对SQLite DbConnection的引用了.强制GC必须清理它们.SQLite中必定存在错误.
感谢您在底部发布的答案.对于完全相同的情况,我正在挖掘数小时
GC.Collect ();
GC.WaitForPendingFinalizers ();
Run Code Online (Sandbox Code Playgroud)
做了伎俩.
尝试在 dbconnection 上调用 Close
确保 sqllite 进程已终止
您可以使用 Unlocker(免费)实用程序查看哪个进程锁定了您的文件
这可能是SqlLite 的“已知”问题;论坛玩笑建议关闭连接并处理该命令,并建议这将在未来版本中修复(因为此行为与其他 ADO 提供程序不一致)
| 归档时间: |
|
| 查看次数: |
3780 次 |
| 最近记录: |