【问题标题】:How to add unmanaged library reference to NUnit test如何将非托管库引用添加到 NUnit 测试
【发布时间】: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 扩展,并且测试项目是使用模板创建的,该模板也可用作扩展。

【问题讨论】:

    标签: c# c++ visual-studio nunit clr


    【解决方案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...
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2018-03-19
      • 2018-05-03
      • 1970-01-01
      • 1970-01-01
      • 2019-01-08
      • 2021-07-28
      • 2015-11-30
      • 1970-01-01
      • 2016-12-12
      相关资源
      最近更新 更多