2016-05-20 40 views
3

说明当多个单元测试复制相同的文件,运行所有的单元测试失败

我写单元测试的方法,该副本从源文件到目的地。基本上,它包括这样的代码:

public void MyMethod() 
{ 
    // ... 
    File.Copy(source, destination, true); 
    // ... 
} 

以我单元测试项目,我有一个测试文件:(test.png),它位于在我的单元测试项目的Resources文件夹。我已将Copy to Output属性设置为Always

我有3个单元测试正在测试这个方法。

当他们击中复制文件的代码行时:source = "Resources\\test.png"

问题

当我单独运行单元测试,他们都通过,一切都很好。 然而,当我在运行Visual Studio的所有测试中,我得到这个运行时错误和单元测试失败:

System.IO.DirectoryNotFoundException

找不到路径的一部分“资源\测试巴纽”。

我的思考......(修订版)

  • 可能是因为Visual Studio中同时运行的每个单元测试在一个单独的线程,他们都访问同一文件在同一时间?

  • 我认为对于每个单元测试,Visual Studio正在清除bin/Debugbin/Release文件夹。然后它复制该文件夹中所有需要的项目文件。这有时导致文件实际上不存在?

问题

我怎样才能解决这个问题?

是否有配置的任何设置来解决这个问题?

当多个单元测试访问同一文件时,如何在Visual Studio(和Team City)中运行所有单元测试?

+0

这可能帮助,如果你可以分享这些3次测试的整个代码。 –

回答

1

发生了什么事,因为我运行批处理的单元测试时使用相对路径来测试文件,因为某些原因,测试运行工作目录比运行单独的测试时,因此它找不到目录不同。然后

private string GetFilePath([CallerFilePath] string path = "") 
    { 
     return path; 
    } 

所以我用这个功能来构建的测试文件的绝对路径

string projectDir = Path.GetDirectoryName(GetFilePath()); 
    string testFile = Path.Combine(projectDir, @"Resources\test.png"; 
0

我推测你的问题是,由于明确的“目录未找到”异常,所测试的方法之一会改变目录。文件锁定或任何并发问题都不可能导致描述的行为。

+0

任何单元测试都不会改变我的代码中的目录。我更新了这个问题,它可能会有所帮助。谢谢。 –

1

访问相同的文件不应该是一个问题。确保您没有清理夹具(TestSuite级别)来删除文件。因为从例外情况来看,运行测试后文件正在被删除。

并发读取操作很好,并且完全合法。如果你的单元测试覆盖文件,那么这是一个问题。

+0

我有一个清理,它删除'目的地'。但是'source ='Resources \\ test.png''总是固定的并且永远不会被删除。 –

2

您可以尝试按照从MSDN: Executing Unit Tests in parallel on a multi-CPU/core machine设置parallelTestCount1的说明排除多线程问题。如果测试现在通过,您已经缩小了问题范围。

但是,如果当你在一组运行它们的测试仍然失败 - 我觉得这是更可能的情况 - ,那么我的建议是检查这些测试共享任何状态。您所描述的图案;典型地是由被(错误地)共享状态,并且状态被这些测试修改,使一个或多个测试失败的测试表现出的症状(即通过在隔离时不是孤立失败)。

0

如果单元测试,你真不该测试File.Copy(或任何文件类的方法)是否有效,因为你没有写代码。相反,你应该测试你的代码是否与文件类型正确相互作用(即没有将它传递正确的源文件名,desination文件名和覆盖值,当你所谓的“复制”)。首先为File类创建一个接口,并为其实现接口的包装器;

public interface IFileWrapper 
{ 
    void Copy(string sourceFileName,string destFileName,bool overwrite); 
    //Other required file system methods and properties here... 
} 

public class FileWrapper : IFileWrapper 
{ 
    public void Copy(string sourceFileName, string destFileName, bool overwrite) 
    { 
     File.Copy(sourceFileName, destFileName, overwrite); 
    } 
} 

然后,你应该让你测试的类包括IFileWrapper参数(dependency injection)。在你的单元测试中,你可以使用一个像Moq这样的模拟框架,或者你可以编写自己的模拟器;

public class MockFileWrapper : IFileWrapper 
{ 
    public string SoureFileName { get; set; } 
    public string DestFileName { get; set; } 
    public bool Overwrite { get; set; } 
    public void Copy(string sourceFileName, string destFileName, bool overwrite) 
    { 
     SoureFileName = sourceFileName; 
     DestFileName = destFileName; 
     Overwrite = overwrite; 
    } 
} 

在实际实施中传递FileWrapper作为IFileWrapper参数,但在单元测试中传递MockFileWrapper。通过检查mockFileWrapper的单元测试的属性,你现在就可以决定你的类调用是否复制,它是如何被调用。由于您不再在单元测试之间共享真实文件,您将避免测试共享状态或潜在锁定文件的机会。

相关问题