NUnit [TearDown]失败-正在访问我的文件的进程是什么? [英] NUnit [TearDown] fails -- what process is accessing my files?

查看:176
本文介绍了NUnit [TearDown]失败-正在访问我的文件的进程是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

最终我找到了问题的解决方案(在问题的底部).

Final I found a solution to the problem (at the bottom of the question).

我遇到一个Nunit问题,这使我感到悲伤. 实际上,它看起来更像是SQLite的问题,但我不确定100%.

I've got an Nunit problem that's causing me grief. actually it looks more like a SQLite problem, but I'm not 100% certain yet.

我的TestFixture的安装程序会生成一个随机文件名,该文件名在我的每个测试中都用作SQLite数据库.

My TestFixture has a setup that generates a random filename that's used as a SQLite database in each of my tests.

[Setup]
public void Setup()
{
    // "filename" is a private field in my TestFixture class
    filename = ...; // generate random filename
}

我的每个测试在访问数据库的每种方法中都使用此构造:

Each of my tests use this construct in each method that accesses the database:

[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;
}

以便所有方法都使用一个辅助方法Connect().我假设using() { }构造正在TestMethod()末尾的连接上调用Dispose()并释放与SQLite数据库文件的连接.

So that one helper method Connect() is used by all the methods. I'm assuming that the using() { } construct is calling Dispose() on the connection at the end of TestMethod() and freeing up the connection to the SQLite database file.

我的问题出在我的[TearDown]方法中:

The problem I have is in my [TearDown] method:

    [TearDown]
    public void Cleanup()
    {
        File.Delete(filename); // throws an IOException!
    }

每次测试我都会得到一个例外:

With every test I get an exception:

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]时都会失败,因此我最终得到一个充满临时数据库文件的目录(每个测试一个,每个都有不同的名称)和一堆失败的测试.

All of the tests fail when they get to the [TearDown], so I end up with a directory full of temporary databse files (one per test, each with a different name) and a whole bunch of failed tests.

正在访问文件的进程是什么?我不知道第二个进程如何访问文件. connection已经完全超出范围,在我尝试删除文件时已被Dispose()d处理,因此它不能与SQLite相关.可以吗?

What process is accessing the file? I don't get how a second process could be accessing the file. The connection has completely gone out of scope and been Dispose()d by the time I'm trying to delete the file, so it can't be something SQLite related. Can it?

请注意,如果我运行所有测试或仅运行一个测试,我将得到相同的结果.

Note that I get the same result if I run all the tests or just a single test.

更新:因此,我也尝试了DbCommand对象的Dispose()处理,因为我没有这样做(我假设其他所有Dispose()处理DbConnection的ADO.NET提供程序还Dispose()在该连接上的所有命令.)现在,它们看起来像:

Update: So I tried Dispose()ing of my DbCommand objects as well, since I wasn't doing that (I assumed that every other ADO.NET provider that Dispose()ing the DbConnection also Dispose()s any commands on that connection.) So now they look like:

[Test]
public void TestMethod()
{
    using (var connection = Connect())
    {
        using (var command = connection.CreateCommand())
        {
        // do database activity using connection

        }
    }
}

没什么区别-File.Delete()行仍然抛出IOException. :-(

It didn't make any difference -- the File.Delete() line still throws an IOException. :-(

如果我删除[TearDown]中的那一行,那么我所有的测试都通过了,但是我剩下了一堆临时数据库文件.

If I remove that one line in [TearDown] then all my tests pass, but I'm left with a whole bunch of temporary database files.

另一个更新: 效果很好:

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]方法启动时,肯定再也没有对SQLite DbConnection的引用.但是,强制GC必须清除它们. SQLite中一定有一个错误.

I ran the unit tests through the debugger, and when the [TearDown] method starts there are definitely no references to the SQLite DbConnection around any more. Forcing a GC must clean them up though. There must be a bug in SQLite.

推荐答案

感谢底部发布的答案.我在完全相同的情况下挖掘了几个小时,而

Thanks for the posted answer at the bottom. I was digging for hours for exactly the same case and

GC.Collect ();
GC.WaitForPendingFinalizers ();

成功了!

这篇关于NUnit [TearDown]失败-正在访问我的文件的进程是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆