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

时间:2017-10-09 18:17:47

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

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

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

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

2 个答案:

答案 0 :(得分:0)

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

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

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

答案 1 :(得分:0)

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

但是,我设法找到一个有趣的属性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); } ,可以用来标记函数SQL DEMO。值得庆幸的是,这是在运行测试的同一过程中实现的,因此我们可以使用它以优雅的方式更改Path变量。这是我用来改变Path的代码,它也可以区分运行它们的架构:

[TestFixture]
public class UnitTests
{
    [OneTimeSetUpAttribute]
    public void TestFixtureSetup()
    {
        RegisterLibs();
    }

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

然后可以在测试中使用:

// Object definition
function OriginalOwner(prop) { this.prop = prop; }
OriginalOwner.prototype.aFunc = function(arg) { return this.prop + arg; }

// Object instance
var owner = new OriginalOwner("Returned ");

// Example function bindings
var boundFunc = owner.aFunc.bind(owner);
var reboundFunc = boundFunc.bind(boundFunc.owner, "myArgument");

// Calling rebound function
console.log(reboundFunc()); // outputs "Returned myArgument"