C# VisualStudio NUnit3TestAdapter与第三方DLL的测试项目
我有一个测试项目C# VisualStudio NUnit3TestAdapter与第三方DLL的测试项目,c#,visual-studio,nunit-3.0,C#,Visual Studio,Nunit 3.0,我有一个测试项目Proj_Test,有两个nuget包 <packages> <package id="NUnit" version="3.6.0" targetFramework="net45" /> <package id="NUnit3TestAdapter" version="3.6.0" targetFramework="net45" /> </packages> 设置似乎被忽略 如何管理测试的这些依赖关系 编辑: 我想我是怎么
Proj_Test
,有两个nuget包
<packages>
<package id="NUnit" version="3.6.0" targetFramework="net45" />
<package id="NUnit3TestAdapter" version="3.6.0" targetFramework="net45" />
</packages>
设置似乎被忽略
如何管理测试的这些依赖关系
编辑:
我想我是怎么了
专用程序集部署在与应用程序相同的目录结构中。如果为PrivateBinPath指定的目录不在ApplicationBase下,则将忽略它们
创建副本真的是唯一的解决方案吗?如果找不到更好的解决方案,请尝试自己解决
using ConsoleApplication6;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Reflection;
namespace UnitTestProject1
{
[TestClass]
public class UnitTest1
{
[TestInitialize]
public void Init()
{
AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.AssemblyResolve += MyResolveEventHandler;
}
[TestMethod]
public void TestMethod1() { Assert.AreEqual(new MyClass().DoSomething(), 1); }
[TestMethod]
public void TestMethod2() { Assert.AreEqual(new MyClass().DoSomething(), 1); }
private Assembly MyResolveEventHandler(object sender, ResolveEventArgs args)
{
return Assembly.LoadFile(@"C:\MyPath\MyAssembly.dll");
}
}
}
不幸的是,程序集探测只能在子目录上工作,所以您不能使用它…多亏了George Vos的回答,这就是我最终实现的
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
//https://github.com/nunit/docs/wiki/SetUpFixture-Attribute
//A SetUpFixture outside of any namespace provides SetUp and TearDown for the entire assembly.
[SetUpFixture]
class GlobalSetup
{
[DllImport("kernel32", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern int SetDllDirectory(string NewDirectory);
static HashSet<string> directories = new HashSet<string>
{
@"D:\Drive\AnyThirdParty\"
};
[OneTimeSetUp]
public void RunBeforeAnyTests()
{
AddManagedHandler();
SetNativeDirectories();
}
private void SetNativeDirectories()
{
if(directories.Count() != 1)
{
//TODO: add support for multiple directories
throw new NotImplementedException("current implementation only supports exactly one directory");
}
if (0 == SetDllDirectory(directories.First()))
{
throw new Exception("SetDllDirectory failed with error " + Marshal.GetLastWin32Error());
}
}
private void AddManagedHandler()
{
AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
}
private Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
IEnumerable<string> candidates = FindCandidates(new AssemblyName(args.Name));
return Assembly.LoadFrom(candidates.First());
}
private static IEnumerable<string> FindCandidates(AssemblyName assemblyname)
{
List<string> candidates = new List<string>();
foreach (var path in directories)
{
string candidate = string.Format(@"{0}{1}.dll", path, assemblyname.Name);
if (File.Exists(candidate))
{
candidates.Add(candidate);
}
}
if (!candidates.Any())
{
throw new FileNotFoundException(string.Format("Can not find assembly: '{0}.dll'", assemblyname.Name));
}
return candidates;
}
}
使用NUnit.Framework;
使用制度;
使用System.Collections.Generic;
使用System.IO;
使用System.Linq;
运用系统反思;
使用System.Runtime.InteropServices;
使用系统文本;
//https://github.com/nunit/docs/wiki/SetUpFixture-Attribute
//任何命名空间之外的SetUpFixture为整个程序集提供设置和拆卸。
[固定装置]
类全局设置
{
[DllImport(“kernel32”,CharSet=CharSet.Unicode,SetLastError=true)]
私有静态外部int SetDllDirectory(字符串NewDirectory);
静态哈希集目录=新哈希集
{
@“D:\Drive\AnyThirdParty\”
};
[一次性设置]
public void RunBeforeAnyTests()
{
AddManagedHandler();
SetNativeDirectories();
}
私有无效SetNativeDirectories()
{
if(directories.Count()!=1)
{
//TODO:添加对多个目录的支持
抛出新的NotImplementedException(“当前实现仅支持一个目录”);
}
if(0==SetDllDirectory(directories.First())
{
抛出新异常(“SetDllDirectory失败,错误为”+Marshal.GetLastWin32Error());
}
}
私有void AddManagedHandler()
{
AppDomain currentDomain=AppDomain.currentDomain;
currentDomain.AssemblyResolve+=currentDomain_AssemblyResolve;
}
私有程序集CurrentDomain_AssemblyResolve(对象发送方,ResolveEventArgs args args)
{
IEnumerable candidates=FindCandidates(新的AssemblyName(args.Name));
返回Assembly.LoadFrom(candidates.First());
}
私有静态IEnumerable FindCandidates(AssemblyName AssemblyName)
{
列表候选者=新列表();
foreach(目录中的var路径)
{
stringcandidate=string.Format(@“{0}{1}.dll”,路径,assemblyname.Name);
如果(文件存在(候选))
{
候选人。添加(候选人);
}
}
如果(!candidates.Any())
{
抛出新的FileNotFoundException(string.Format(“找不到程序集:{0}.dll',assemblyname.Name));
}
返回候选人;
}
}
我查看了“AssemblyResolve”,似乎您需要按方法分离调用。因此,我在“OneTimeSetUp”中尝试了它,但没有触发事件-我可能遗漏了什么?@Johannes我想不出原因。我回家后会尝试。我认为我的依赖项之一是本机dll。这可能与此有关。@Johannes我看不出TestInitialize有问题……请尝试在MyResolveEventHandler中添加断点和Try/catch,并检查未能加载的程序集(请参见args.Name)还有whyok-在我的最小示例中,我注意到a)您的代码适用于托管程序集,b)我需要为本机DLL设置路径。使用函数AddDllDirectories并不简单,因此为了兼容性,我使用SetDllDirectories。
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
//https://github.com/nunit/docs/wiki/SetUpFixture-Attribute
//A SetUpFixture outside of any namespace provides SetUp and TearDown for the entire assembly.
[SetUpFixture]
class GlobalSetup
{
[DllImport("kernel32", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern int SetDllDirectory(string NewDirectory);
static HashSet<string> directories = new HashSet<string>
{
@"D:\Drive\AnyThirdParty\"
};
[OneTimeSetUp]
public void RunBeforeAnyTests()
{
AddManagedHandler();
SetNativeDirectories();
}
private void SetNativeDirectories()
{
if(directories.Count() != 1)
{
//TODO: add support for multiple directories
throw new NotImplementedException("current implementation only supports exactly one directory");
}
if (0 == SetDllDirectory(directories.First()))
{
throw new Exception("SetDllDirectory failed with error " + Marshal.GetLastWin32Error());
}
}
private void AddManagedHandler()
{
AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
}
private Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
IEnumerable<string> candidates = FindCandidates(new AssemblyName(args.Name));
return Assembly.LoadFrom(candidates.First());
}
private static IEnumerable<string> FindCandidates(AssemblyName assemblyname)
{
List<string> candidates = new List<string>();
foreach (var path in directories)
{
string candidate = string.Format(@"{0}{1}.dll", path, assemblyname.Name);
if (File.Exists(candidate))
{
candidates.Add(candidate);
}
}
if (!candidates.Any())
{
throw new FileNotFoundException(string.Format("Can not find assembly: '{0}.dll'", assemblyname.Name));
}
return candidates;
}
}