代码之家  ›  专栏  ›  技术社区  ›  Tim

使用单独AppDomain的单元测试代码

  •  0
  • Tim  · 技术社区  · 5 年前

    我有使用AppDomain动态加载插件的代码。我有一个名为PluginFinder的私有内部类来完成这项工作。这一切都在生产环境中工作,但是我现在正尝试为它编写MS单元测试,并且我收到一个错误,说找不到程序集。

    要清楚的是,主类创建AppDomain并在其中运行PluginFinder,以加载使用正确接口找到的类。加载类后,控件将返回到默认的AppDomain。仅在加载过程中使用PlugInfender。

    我使用下面的代码创建环境:

                //  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);
    

    PlugInfender使用默认的构造函数,是一个私有的内部类。我得到的例外情况如下:

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

    我找到了 this 解决方案,它建议nunit在多个appdomain中运行,这使得没有插件就无法测试appdomain。我正在使用MS单元测试,但我怀疑这里也可能发生这种情况。

    ****已解决****

    正如下面的注释中提到的,我需要使用重载构造函数。我修改了我的代码(如下所示),它起作用了。

    // 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 回复  |  直到 5 年前
        1
  •  1
  •   Mike Zboray    5 年前

    我不太确定nunit在这里做什么,但问题可能是新的appdomain的基目录不是您所期望的。创建新域时,请考虑使用父域的设置信息或直接从当前域中复制基:

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