简体   繁体   中英

VisualStudio NUnit3TestAdapter testing project with third party dlls

I have a testing project Proj_Test with two nuget packages.

<packages>
  <package id="NUnit" version="3.6.0" targetFramework="net45" />
  <package id="NUnit3TestAdapter" version="3.6.0" targetFramework="net45" />
</packages>

Proj_Test has a reference to the tested project Proj . 布局

Proj has references to several other dlls that need to be loaded. Where can I add this information so that I can start the tests using the NUnit3TestAdapter from within my IDE without actually copying the dlls to the output folder.

There was a solution for the Nunit2 Runners . But I fail when attempting to use that for Nunit3 via NUnit3TestAdapter.

According to the tips and tricks section i added a settings file Test.runsettings via the menu.

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

The setting seems to be ignored.

How can I manage these dependencies for my tests?

EDIT: This is what happened to me I think.

Private assemblies are deployed in the same directory structure as the application. If the directories specified for PrivateBinPath are not under ApplicationBase, they are ignored.

Is creating a copy really the only solution?

If you can't find anything better,try to resolve it yourself

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

Unfortunately assembly probing works only on subdirectories so you can't use it...

Thanks to George Vovos answer, this is what I ended up implementing.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM