【问题标题】:VisualStudio NUnit3TestAdapter testing project with third party dlls带有第三方 dll 的 VisualStudio NUnit3TestAdapter 测试项目
【发布时间】:2017-01-10 16:41:23
【问题描述】:

我有一个测试项目 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 引用了测试项目Proj

Proj 引用了其他几个需要加载的 dll。 我在哪里可以添加这些信息,这样我就可以在我的 IDE 中使用 NUnit3TestAdapter 开始测试,而无需实际将 dll 复制到输出文件夹。

a solution for the Nunit2 Runners。但是当我试图通过 NUnit3TestAdapter 将它用于 Nunit3 时我失败了。

根据tips and tricks section,我通过菜单添加了一个设置文件Test.runsettings

<RunSettings>
  <NUnit>
    <PrivateBinPath>D:\Drive\AnyThirdParty</PrivateBinPath>
  </NUnit>
</RunSettings>

该设置似乎被忽略了。

如何为我的测试管理这些依赖项?

编辑: This is 我想我发生了什么事。

私有程序集部署在与应用程序相同的目录结构中。如果为 PrivateBinPath 指定的目录不在 ApplicationBase 下,则它们将被忽略。

创建副本真的是唯一的解决方案吗?

【问题讨论】:

    标签: c# visual-studio nunit-3.0


    【解决方案1】:

    如果找不到更好的,请尝试自己解决

    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");
            }
        }
    }
    

    不幸的是,程序集探测仅适用于子目录,因此您无法使用它...

    【讨论】:

    • 我查看了“AssemblyResolve”,您似乎需要按方法分开调用。所以我在“OneTimeSetUp”中尝试了它,但事件没有被触发——我可能遗漏了什么?
    • @Johannes 我想不出理由。等我回家再试试
    • 我认为我的依赖项之一是本机 dll。这可能与它有关。
    • @Johannes 我没有看到 TestInitialize 有问题...尝试在 MyResolveEventHandler 中添加断点和 try/catch 并检查哪个程序集加载失败(参见 args.Name)以及原因
    • 好的——所以在处理我的最小示例时,我注意到a)您的代码适用于托管程序集,b)我需要设置本机 dll 的路径。使用 AddDllDirectories 函数并非易事,所以我使用 SetDllDirectories 来实现兼容性。
    【解决方案2】:

    感谢 George Vovos 的回答,这就是我最终实施的。

    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;
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2016-02-05
      • 1970-01-01
      • 2013-08-29
      • 1970-01-01
      • 1970-01-01
      • 2015-03-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多