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

son*_*iot 1 .net c# filesystems unit-testing process

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

如果不存在,SetUp()函数将创建备份.

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

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

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

umb*_*rsw 7

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

  1. 创建该文件的临时副本
  2. 执行临时文件上正在测试的操作
  3. 释放临时文件的所有句柄(关闭所有连接)
  4. 删除临时文件

使用此模式,将访问该文件的唯一进程将是运行单元测试的线程.

使用功能: 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);
Run Code Online (Sandbox Code Playgroud)


Sco*_*ott 6

我在使用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);
}
Run Code Online (Sandbox Code Playgroud)

[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"));
}
Run Code Online (Sandbox Code Playgroud)

[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);
    }
}
Run Code Online (Sandbox Code Playgroud)