我刚刚开始使用NUnit为我的项目提供一些测试覆盖率。
在我的主library.dll中,我需要从库,library.xml附带的外部文件中加载配置数据。
当我使用该库时,这工作正常,因为我使用以下内容来获取查找配置文件的目录:
string settingspath = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
我注意到的问题是,当我使用NUnit进行单元测试时,它会将我的程序集复制到Shadow Copy,但是不会带任何其他文件,所以当然我的init因为丢失配置文件。
我是否应该做一些不同的事情来从我的库中找到配置文件? (这是一个服务器应用程序,我不想使用标准的应用程序设置,或用户的本地设置等)
答案 0 :(得分:48)
使用可以使用TestContext.CurrentContext.TestDirectory
as mentioned by Charlie Poole from NUnit here:
需要访问与测试程序集相同的目录中的文件 禁用卷影副本的最常见原因。然而, 这是假的。
NUnit不会复制任何程序集:shadow copy是.NET的一个功能 本身。因此,问题需要被视为“我怎么能 访问文件的位置?“而不是”如何获取文件 复制到我认为它应该的位置?“
有三种方法可以找到位于同一文件中的文件 目录作为程序集:
1)使用Assembly.Codebase - 这将为您提供URI的位置, 然后你必须转换到适当的路径。
2)使用NUnit历史上设置的当前目录 包含执行测试程序集的目录。但是,这可能 未来版本不适用。
3)使用NUnit的TestContext.CurrentContext.TestDirectory,即 可在最新版本中找到。
所有这些方法实际上都使用了Assembly.Codebase 覆盖,NUnit正在进行正确转换URI的工作 #2和#3。使用Assembly.Location的常见方法是不正确的,除非您确实需要卷影副本的位置 高速缓存中。
答案 1 :(得分:19)
为了在我的单元测试中使用参考文件,我使用Assembly.Codebase,即使打开了Shadow Copying,它也能正常工作。你可能想尝试一下..
它返回Uri格式的字符串..所以你需要从codebase字符串创建一个Uri实例,并使用Uri.LocalPath来获取实际的文件夹路径。
但是对于生产代码,应该从众所周知的地方检索BaseFolder(例如,通过Windows上的安装程序设置的注册表项)。所有文件查找都应该来自这个baseFolder。
答案 2 :(得分:13)
即使影子复制处于活动状态,AppDomain.CurrentDomain.BaseDirectory
也会指向测试DLL的原始位置。
但是,如果您可以将测试数据作为资源嵌入DLL中,那么它会更加安全,因为没有额外的文件会丢失。
答案 3 :(得分:1)
您可以使用/noshadow
开关在命令行上禁用卷影复制。命令行选项记录在here
外部文件是否设置为dll构建的一部分?如果将它包含在项目中并将其设置为始终在文件属性中的“复制到输出”中复制,则 应该转到我认为的影子目录。
这可能会对你有所帮助。
答案 4 :(得分:1)
我们在测试项目中包含测试资源(在本例中为'TestData'文件夹)。
在Visual Studio中为要在测试标记中访问的资源
当项目构建将图像留在'bin \ Debug'文件夹中时
然后你写了路径
string fullImagePath = @".\TestData\vcredist.bmp";
答案 5 :(得分:1)
您已经注意到,Assembly.Location
在NUnit的ShadowCopyCache中的某个地方返回了一个无用的临时路径,这对于避免锁定文件和防止重新编译是必需的。
我还有其他问题:首先, NUnit 2 GUI运行程序与 NUnit 3 GUI运行程序(现在称为TestCentric)不同。其次,有时我需要从另一个可执行文件调用测试方法。作为参考,这是我得到的路径:
NUnit 2:
AppDomain.CurrentDomain.BaseDirectory = @"C:\PathToNUnitProject\"
NUnit.Framework.TestContext.CurrentContext.WorkDirectory = @"C:\PathToNUnitProject"
NUnit.Framework.TestContext.CurrentContext.TestDirectory = @"C:\PathToNUnitProject\bin\Debug"
NUnit 3:
AppDomain.CurrentDomain.BaseDirectory = @"C:\PathToNUnitProject\bin\Debug\"
NUnit.Framework.TestContext.CurrentContext.WorkDirectory = @"C:\TestCentric\testcentric-gui-1.2.0"
NUnit.Framework.TestContext.CurrentContext.TestDirectory = @"C:\PathToNUnitProject\bin\Debug"
从NUnit外部调用测试方法时:
AppDomain.CurrentDomain.BaseDirectory = something else entirely
NUnit.Framework.TestContext.CurrentContext.WorkDirectory = Exception
NUnit.Framework.TestContext.CurrentContext.TestDirectory = Exception
对我来说,解决方案是:在尝试捕获中使用NUnit.Framework.TestContext.CurrentContext.TestDirectory
,就像Jeff的回答一样。
如果没有抛出,则在两个NUnit版本上返回的路径都是相同的。
答案 6 :(得分:0)
遇到同样的问题......以下是我的锻炼:
在SUT运行之前,以这种方式更新AppDomain的基本目录....
String root_path = "{{your path}}";
AppDomain.CurrentDomain.SetData("APPBASE", root_path);
答案 7 :(得分:-12)
当进行单元测试时,通常建议避免外部依赖,例如文件系统和数据库,通过模拟/删除调用它们的例程 - 这样你的测试就会更加本地化,更不易碎,更快。查看是否可以通过提供虚假配置信息来删除依赖项。