确定程序集目录时NUnit出现问题

时间:2010-12-02 14:31:14

标签: .net nunit

我刚刚开始使用NUnit为我的项目提供一些测试覆盖率。

在我的主library.dll中,我需要从库,library.xml附带的外部文件中加载配置数据。

当我使用该库时,这工作正常,因为我使用以下内容来获取查找配置文件的目录:

string settingspath = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);

我注意到的问题是,当我使用NUnit进行单元测试时,它会将我的程序集复制到Shadow Copy,但是不会带任何其他文件,所以当然我的init因为丢失配置文件。

我是否应该做一些不同的事情来从我的库中找到配置文件? (这是一个服务器应用程序,我不想使用标准的应用程序设置,或用户的本地设置等)

8 个答案:

答案 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中为要在测试标记中访问的资源 In Visual Studio for the resource to access in the test mark

当项目构建将图像留在'bin \ Debug'文件夹中时 When project builds leaves the image on the 'bin\Debug' folder

然后你写了路径

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)

当进行单元测试时,通常建议避免外部依赖,例如文件系统和数据库,通过模拟/删除调用它们的例程 - 这样你的测试就会更加本地化,​​更不易碎,更快。查看是否可以通过提供虚假配置信息来删除依赖项。