我们正在使用Xunit进行测试。我们使用Xunit插件通过内置的Visual Studio 2013 Test Runner运行我们的测试。
问题是某些测试需要引用文件系统上的文件。似乎Xunit(或VS Test Runner-不确定哪个)在执行测试之前将bin目录中的汇编(而不是bin目录中的任何支持文件)复制到另一个目录,因此找不到我们的测试文件。 [MS Testing框架指定列出要复制的文件的属性,但Xunit没有。]
如何 禁用此复制行为,或者以编程方式确定原始bin/
目录位置以获取文件?
似乎大多数提议的解决方案(包括在Xunit错误跟踪器网站上)建议将文件存储为嵌入式资源而不是“复制始终”文件。但是,这并不总是实用的,例如:测试文件操作代码,以及(在一种情况下)需要Sqlite数据库文件的代码。
答案 0 :(得分:30)
好的,典型的,就在我发布问题时,我自己找到答案......
要点是程序集的复制(阴影复制)似乎是由.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);
...其中relativePath
是相对于Bin\
目录的路径。
答案 1 :(得分:11)
经过一些搜索后,我在这里找到了解决方案:https://msdn.microsoft.com/en-us/library/ms182475.aspx。
特别是,第一步对我来说已经足够了:
如果它们特定于一个测试项目,请将它们作为内容文件包含在Visual Studio测试项目中。在“解决方案资源管理器”中选择它们,并将“复制到输出”属性设置为“复制为更新。”
与以下代码相关联:
var filename = "./Resources/fake.pdf"
File.OpenRead(filename)
答案 2 :(得分:3)
我在Mac上运行.Net Core 1.0。 Assembly.GetExecutingAssembly
不可用。我改为使用以下代码:
var location = typeof(YourClassName).GetTypeInfo().Assembly.Location;
var dirPath = Path.GetDirectoryName(location);
return Path.Combine(dirPath, relativePath);
relativePath
是相对于DLL目录的路径。
答案 3 :(得分:3)
在尝试识别目录和复制文件(似乎有多个目录,很难确定正确的目录)后,我发现您可以关闭卷影复制功能。此时,单元将再次测试bin / {configuration}文件夹中的参考内容。
要这样做,请遵循指示here。好像将shadowCopy
设置为false一样简单:
{
"shadowCopy": false
}
我不清楚此设置是否与其他设置(例如appDomain
)有任何不利的相互作用。如果有人知道,将欢迎您发表评论。
答案 4 :(得分:2)
从 .NET5
(可能更早)开始,CodeBase
不再有效,因此现在的解决方案是先将您的所有文件复制到 bin 目录并将其用作您的已知位置。>
现在让这一切正常的原因是,您可以轻松地从 csproj
文件中将目录复制到 bin 文件夹中,这在过去总是令人头疼。
<ItemGroup>
<None
Include="TestFiles\**"
CopyToOutputDirectory="PreserveNewest"
LinkBase="TestFiles\" />
</ItemGroup>
其中 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);
}
}