Исключение, создающее домен приложения в тесте NUnit

#c# #unit-testing #plugins #nunit #appdomain

#c# #модульное тестирование #Плагины #nunit #домен приложения #appdomain

Вопрос:

Я написал библиотеку плагинов, которая ищет в каталоге сборки, которые экспортируют реализации данного интерфейса. Это делается путем загрузки всех сборок во временный домен приложения в контексте только для отражения и поиска по экспортированным типам. Затем временный домен приложения выгружается, интересующие сборки загружаются в домен приложения по умолчанию, а объекты найденных типов затем создаются для использования через искомый интерфейс.

Я пытаюсь написать несколько модульных тестов для этого процесса, используя NUnit, но я получаю исключение FileNotFoundException только в модульных тестах, когда пытаюсь подключить событие ReflectionOnlyAssemblyResolve. Вот простой пример:

 using System;
using System.Reflection;
using NUnit.Framework;

namespace NUnitAppDomains
{
    [TestFixture]
    public class TestClass
    {
        [Test]
        public void NUnitTest()
        {
            var ad = AppDomain.CreateDomain("someName");

            // this next line throws a FileNotFoundException, complaining about not being 
            // able to find the test assembly itself... o.O
            ad.ReflectionOnlyAssemblyResolve  = SomeHandler;

            AppDomain.Unload(ad);
        }

        static Assembly SomeHandler(object sender, ResolveEventArgs args)
        {
            // some code would be here

            throw new NotImplementedException();
        }
    }
}
  

Я пытался протестировать код на некоторых фиктивных сборках в известном месте, некоторые из которых содержат / не содержат допустимые imlementation / s. Мой код не поддается модульному тестированию или, если да, как я могу избежать этих исключений? Спасибо

Комментарии:

1. Правильно сформулированный вопрос, спасибо за SSCCE . Добро пожаловать в SO!

Ответ №1:

Проблема в том, что ваш код выполняется в другой базе приложений (NUnit, Visual Studio или что-то еще, выполняющее ваш тест). Когда вы создаете домен без указания базы, он использует базу приложения, выполняющего ваш код, например «Program Files NUnit Bin», и, конечно, ваша сборка там не найдена.

Решение состоит в том, чтобы использовать базу приложений вашего кода при создании AppDomain , которую вы можете получить из текущего потока:

 var callingDomain = Thread.GetDomain();
var setup = new AppDomainSetup 
            { 
                ApplicationBase = callingDomain.SetupInformation.ApplicationBase 
            };

var ad = AppDomain.CreateDomain("someName", null, setup);
  

В этом сообщении в блоге немного подробнее, но не намного. Тем не менее, стоит прочитать.

Комментарии:

1. Отлично, спасибо. Изначально я предполагал, что мне может понадобиться IAppDomainFactory с этим для реализации модульных тестов и моего исходного кода для производственной реализации, но, похоже, это подходит для обоих, поскольку оно просто делает каталог поиска явным?

2. Эх, это компромисс. Наличие an NUnitAppDomainFactory может быть немного более конкретным, но, конечно, добавляет немного больше сложности. Если вы используете это для обоих, я бы оставил большой жирный комментарий в коде о том, почему это делается таким образом.