如何将非托管库引用添加到 NUnit 测试

Posted

技术标签:

【中文标题】如何将非托管库引用添加到 NUnit 测试【英文标题】:How to add unmanaged library reference to NUnit test 【发布时间】:2017-10-09 18:17:47 【问题描述】:

问题:如何在运行测试时使 NUnit 可以使用本机库,以便在启动时加载它?

背景:我最近开始使用 NUnit 进行测试,我正在努力设置一个涉及非托管(本机)库的测试(我们称之为 x.dll)。我正在测试的项目是围绕这个库的托管 c++/CLI 包装器。我有引用包装器的 NUnit c# 测试项目,所以我可以使用那里定义的函数。问题是我运行测试时,抛出System.IO.FileNotFoundException,表示找不到x.dll。我需要以某种方式将 NUnit 指向它的位置,或者让它将 dll 复制到执行目录中(隐藏在 temp 目录中的某处),但在相当广泛的搜索之后找不到如何做到这一点 - 可能缺少正确的关键字。

我在 Visual Studio 中使用 NUnit 3 扩展,并且测试项目是使用模板创建的,该模板也可用作扩展。

【问题讨论】:

【参考方案1】:

使用非托管程序集的技巧是要知道操作系统使用与 .NET 查找托管引用的方式不同的方法来查找它们。

作为复习:在路径上找到非托管程序集,而在 AppBase 或它下的私有 binpath 中找到托管程序集。

我的猜测是 VS 正在将 x.dll 复制到输出目录中。如果没有,您应该通过将 CopyLocal 设置为 true 来实现。现在,在运行测试之前,将该目录添加到路径的开头。如果您还没有使用脚本,那么您可能必须创建一个才能执行此操作。

【讨论】:

我应该使用什么方法来编辑路径(我猜你的意思是环境变量)?是否可以仅在启动时为应用程序(测试)更改它,还是我必须在系统范围内对其进行编辑?我想要前者——不污染系统,也不强迫所有开发人员这样做,但我不确定它是否可行。 测试在加载之前无法执行任何操作,并且在满足所有引用之前无法加载。如果您运行脚本来执行测试,只需在运行 nunit3-console.exe 之前添加到 PATH 环境变量。脚本完成后,该设置不会影响其他任何内容。 谢谢,但我正在使用 Resharper 直接从 Visual Studio 运行测试。我如何将运行nunit3-console 的脚本与此环境集成?在旁注中,多亏了你的回顾,我可能已经设法准确地设置了我需要的东西,只需要在发布之前多尝试一下。【参考方案2】:

因为我希望测试是独立的并且能够使用 Resharper 或 Visual Studio 测试框架(使用 NUnit 扩展)等工具运行,所以我尽量避免像 @Charlie 建议的那样从脚本运行测试,因为我不会知道如何将结果与这些工具集成。

不过,我设法找到了一个有趣的属性OneTimeSetUpAttribute,它可以用来标记函数,以便it will be ran every time before the tests。值得庆幸的是,这是在运行测试的同一进程中实现的,因此我们可以使用它以优雅的方式更改 Path 变量。这是我用来更改 Path 的代码,它还允许区分它们运行的​​架构:

void RegisterLibs()

     const string pathVar = "Path";
     const string fileUriTag = "file:///";

     // Get executable path
     var exePath = System.Reflection.Assembly.GetExecutingAssembly().CodeBase;
     if (exePath.StartsWith(fileUriTag))
         exePath = exePath.Remove(0, fileUriTag.Length);
     // Extract directory
     var exeDir = System.IO.Path.GetDirectoryName(exePath);

     // Get path variable
     var pathVal = Environment.GetEnvironmentVariable(pathVar) ?? "";
     // Simple check for architecture. 
     // 4-byte pointer => 32bit
     // 8-byte pointer => 64bit
     var arch = IntPtr.Size == 4 ? "Win32" : "x64";
     // Prepare new entry for path
     var libPath = $"exeDir\\arch;";
     if (pathVal.Contains(libPath))
          return;
     // Prepend the entry
     pathVal = pathVal.Insert(0, libPath);
     // Update path variable
     Environment.SetEnvironmentVariable(pathVar, pathVal);

然后可以在测试中使用:

[TestFixture]
public class UnitTests

    [OneTimeSetUpAttribute]
    public void TestFixtureSetup()
    
        RegisterLibs();
    

    [Test]
    public void Test1()
    
        // Path is set-up here
        // ...Your test code...
    

【讨论】:

以上是关于如何将非托管库引用添加到 NUnit 测试的主要内容,如果未能解决你的问题,请参考以下文章

将非托管 DLL 部署到输出目录

将非托管 C++ dll 添加到托管 C++ dll

如何将非托管 dll 和托管程序集合并到一个文件中?

将非托管 EXE 作为资源合并到托管 C# 代码中

如何将非托管 C++ 表单嵌入到 .NET 应用程序中?

将非托管数据复制到托管数组中