File.Delete错误“进程无法访问该文件,因为它正被另一个进程使用”

时间:2010-08-06 02:56:46

标签: c# .net unit-testing process filesystems

我编写了一个DotUnit测试套件,用于测试我的应用程序中的一些数据导入功能。它的工作原理是备份一些本地Microsoft Access数据库,让我们称它为“Test.mdb”,称为“Test.mdb.bak”,执行一些数据导入(以及后续的断言检查),然后从备份中恢复原始数据。

如果不存在,则SetUp()函数会创建备份。

TearDown()函数尝试删除'Test.mdb',然后将'Test.mdb.bak'复制到'Test.mdb'。

间歇性地运行测试失败并出现此错误“进程无法访问该文件,因为它正被另一个进程使用”。

我在File.Delete和IO权限上查看了MSDN,但找不到我之后的内容。有没有人知道是否有.NET功能允许我在尝试删除文件之前完全锁定文件?或者在删除时找到正在访问它的进程?

3 个答案:

答案 0 :(得分:7)

您可能会重新考虑您的测试方法。代替:

  1. 创建文件的临时副本
  2. 执行临时文件
  3. 上正在测试的操作
  4. 释放所有句柄(关闭所有连接)到临时文件
  5. 删除临时文件
  6. 使用此模式,将访问该文件的唯一进程是运行单元测试的线程。

    使用功能:System.IO.Path.GetTempFileName();

    http://msdn.microsoft.com/en-us/library/system.io.path.gettempfilename.aspx

    编辑:以下是编码的一种方法:

    var tempFile = System.IO.Path.GetTempFileName();
    System.IO.File.Copy(@"C:\Test.mdb", tempFile, true);
    // 2. Test tempFile
    // 3. Release handles to tempFile, use a using statement around any 
    //    streams or System.IO API's that are using the file in any way.
    System.IO.File.Delete(tempFile);
    

答案 1 :(得分:5)

我在使用SQLite数据库进行单元测试实体框架代码时遇到了类似的问题,其中每个测试需要使用数据库的新实例,因此我的[TestCleanup]方法在数据库上执行File.Delete,但是得到相同的“另一个进程使用”错误。

在我致电File.Delete之前,我必须添加以下内容来解决我的问题。

GC.Collect的();

GC.WaitForPendingFinalizers();

[TestInitialize]
public void MyTestInitialize()
{
    // Copies the embedded resource 'MyDatabase.db' to the Testing Directory
    CommonTestFixture.UnpackFile("MyDatabase.db", this.GetType(), this.TestContext.TestDeploymentDir);
}

[TestCleanup]
public void MyTestCleanup()
{
    // Adding the following two lines of code fixed the issue
    GC.Collect();
    GC.WaitForPendingFinalizers();

    // Removes 'MyDatabase.db' from the testing directory.
    File.Delete(Path.Combine(this.TestContext.TestDeploymentDir, "MyDatabase.db"));
}

[TestMethod]
public void GetVenueTest()
{
    // CreateTestEntities() is a helper that initializes my entity framework DbContext
    // with the correct connection string for the testing database.
    using (var entityFrameworkContext = CreateTestEntities())
    {
        // Do whatever testing you want here:
        bool result = entityFrameworkContext.TestSomething()
        Assert.IsTrue(result);
    }
}

答案 2 :(得分:1)

这两行解决了这个问题。

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

我已在我的代码中对此进行了测试,但效果很好。

--- Jeetendra