Код модульного тестирования, использующий отдельный домен приложений - PullRequest
0 голосов
/ 11 февраля 2019

У меня есть код, который использует AppDomain для динамической загрузки плагинов.У меня есть закрытый внутренний класс с именем PluginFinder, чтобы сделать работу.Все это работает в производственной среде, но сейчас я пытаюсь написать для него модульные тесты MS, и я получаю сообщение об ошибке, в котором говорится, что сборка не может быть найдена.

Для ясности, основной класс создаетAppDomain и запускает в нем PluginFinder для загрузки найденных классов с правильным интерфейсом.Как только классы загружены, управление возвращается к стандартному домену приложений.PluginFinder используется только во время загрузки.

Я использую приведенный ниже код для создания среды:

            //  Create a domain to text for plugins
            AppDomain domain = AppDomain.CreateDomain("PluginLoader");

            //  Set PluginFinder to run in the new domain (assemblyName, typeName)
            (PluginFinder)domain.CreateInstanceAndUnwrap(
                typeof(PluginFinder).Assembly.FullName, typeof(PluginFinder).FullName);

PluginFinder использует конструктор по умолчанию и является закрытым внутренним классом.Ниже приведено исключение:

    ------ Exception ------
Error:  Could not load file or assembly 'MyClass, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.
There was an error creating the Plugin Loader.
Could not load file or assembly 'MyClass, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.

   at System.Reflection.RuntimeAssembly._nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, RuntimeAssembly locationHint, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks)
   at System.Reflection.RuntimeAssembly.nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, RuntimeAssembly locationHint, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks)
   at System.Reflection.RuntimeAssembly.InternalLoadAssemblyName(AssemblyName assemblyRef, Evidence assemblySecurity, RuntimeAssembly reqAssembly, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks)
   at System.Activator.CreateInstance(String assemblyString, String typeName, Boolean ignoreCase, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes, Evidence securityInfo, StackCrawlMark& stackMark)
   at System.Activator.CreateInstance(String assemblyName, String typeName)
   at System.AppDomain.CreateInstance(String assemblyName, String typeName)
   at System.AppDomain.CreateInstanceAndUnwrap(String assemblyName, String typeName)
   at System.AppDomain.CreateInstanceAndUnwrap(String assemblyName, String typeName)
   at MyClass.loadPlugins() in C:\Code\...
---- End Exception ----

Я нашел это решение, которое предполагает, что NUnit работает в нескольких доменах приложений, что делает невозможным тестирование доменов приложений без плагинов.Я использую MS Unit Test, но подозреваю, что это может быть и здесь.

**** RESOLVED ****

Как уже упоминалось в комментарии ниже,Мне нужно было использовать конструктор перегрузки.Я изменил свой код (показанный ниже), и он работал.

// Set up the AppDomainSetup
var setup = new AppDomainSetup();
setup.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory;

// Set up the Evidence
var baseEvidence = AppDomain.CurrentDomain.Evidence;

//  Create a domain to text for plugins
AppDomain domain = AppDomain.CreateDomain("PluginLoader", baseEvidence, setup);

//  Set PluginFinder to run in the new domain (assemblyName, typeName)
PluginFinder finder = (PluginFinder)domain.CreateInstanceAndUnwrap(
    typeof(PluginFinder).Assembly.FullName, typeof(PluginFinder).FullName);

1 Ответ

0 голосов
/ 11 февраля 2019

Я не совсем уверен, что NUnit делает здесь, но проблема, вероятно, в том, что базовый каталог нового домена приложений не соответствует вашим ожиданиям.При создании нового домена рассмотрите возможность использования информации о настройке родительского домена или явного копирования базы непосредственно из текущего домена:

AppDomain.CreateDomain("PlugInLoader", null, AppDomain.CurrentDomain.SetupInformation);
...