如何从Visual Studio中的Xunit测试中引用测试文件?

and*_*ewf 22 xunit.net visual-studio-2013

我们正在使用Xunit进行测试.我们使用Xunit插件通过内置的Visual Studio 2013 Test Runner运行我们的测试.

问题是某些测试需要引用文件系统上的文件.似乎Xunit(或VS Test Runner-不确定哪个)在执行测试之前将bin目录中的汇编(而不是bin目录中的任何支持文件)复制到另一个目录,因此找不到我们的测试文件.[MS Testing框架指定列出要复制的文件的属性,但Xunit没有.]

如何要么禁用此复制行为,否则编程方式确定原bin/来获取文件目录位置?

似乎大多数提议的解决方案(包括在Xunit错误跟踪器站点上)建议将文件存储为嵌入式资源而不是"复制始终"文件.但是,这并不总是实用的,例如:测试文件操作代码,以及(在一种情况下)需要Sqlite数据库文件的代码.

and*_*ewf 34

好的,典型的,就在我发布问题时,我自己找到答案......

要点是组件的复制(阴影复制)似乎是由.NET框架完成的,而不是由Visual Studio或Xunit完成的.

我们一直在使用Assembly.Location定位程序集文件,因此找到测试文件.但是,这是错误的,因为它给了我们Shadow-Copied组件的位置而不是原件.

相反,您应该使用Assembly.CodeBase获取基本汇编代码位置.但是,这是一个(文件)URL,因此有必要从URL中提取路径.新的(C#)代码如下所示:

var codeBaseUrl = new Uri(Assembly.GetExecutingAssembly().CodeBase);
var codeBasePath = Uri.UnescapeDataString(codeBaseUrl.AbsolutePath);
var dirPath = Path.GetDirectoryName(codeBasePath);
return Path.Combine(dirPath, relativePath);
Run Code Online (Sandbox Code Playgroud)

... relativePath相对于Bin\目录的路径在哪里.


Gia*_*tti 14

经过一些搜索后,我在这里找到了解决方案:https://msdn.microsoft.com/en-us/library/ms182475.aspx.

特别是,第一步对我来说已经足够了:

如果它们特定于一个测试项目,请将它们作为内容文件包含在Visual Studio测试项目中.在Solution Explorer中选择它们,并将Copy to Output属性设置为Copy by Newer.

与以下代码相关联:

var filename = "./Resources/fake.pdf"
File.OpenRead(filename)
Run Code Online (Sandbox Code Playgroud)

测试项目(注意资源文件夹) 资源文件夹中的文件大小

  • 这就是答案。其他解决方案不再起作用。谢谢![这里](/sf/answers/135512611/)关于“资源”和“内容”之间差异的解释 (2认同)

bri*_*ler 12

截至.NET5(也许更早),CodeBase不再有效,因此现在的解决方案是首先将所有文件复制到 bin 目录,并将其用作您的已知位置。

过去一直是一件很痛苦的事情,现在变得可以了,因为您可以轻松地从文件中将目录复制到 bin 文件夹csproj

    <ItemGroup>
      <None 
         Include="TestFiles\**" 
         CopyToOutputDirectory="PreserveNewest" 
         LinkBase="TestFiles\" />
    </ItemGroup>
Run Code Online (Sandbox Code Playgroud)

位于TestFiles项目文件夹的根目录中。现在您可以使用以下帮助器方法访问这些文件。

    public static class TestUtils
    {
        public static string GetTestPath(string relativePath)
        {
            var codeBaseUrl = new Uri(Assembly.GetExecutingAssembly().Location);
            var codeBasePath = Uri.UnescapeDataString(codeBaseUrl.AbsolutePath);
            var dirPath = Path.GetDirectoryName(codeBasePath);
            return Path.Combine(dirPath, "TestFiles", relativePath);
        }
    }
Run Code Online (Sandbox Code Playgroud)