简体   繁体   English

使用AppDomain为单元测试提供应用程序调度程序

[英]Use AppDomain to provide application dispatcher for unit tests

Problem: Application.Current is null in a class when running a unit test. 问题:运行单元测试时,类中的Application.Current为null。

Approach to resolve: Create an application domain that will run my test class. 解决方法:创建一个将运行我的测试类的应用程序域。 The application domain will provide a dispatcher for my test class. 应用程序域将为我的测试类提供一个调度程序。

Code example: 代码示例:

        MyClassInTheAssembly myClass;
        string path = @"C:\\pathToTheDll\\MyAssembly.dll";
        path = path.Replace(@"\\", @"\");
        AppDomainSetup setup = new AppDomainSetup { PrivateBinPath = path };
        AppDomain domain = AppDomain.CreateDomain("MyDomain", null, setup);

        myClass = (MyClassInTheAssembly)domain.CreateInstanceFromAndUnwrap(path, typeof(MyClassInTheAssembly).FullName);

The myClass object can be used to unit test any public methods that use Application.Current.Dispatcher. myClass对象可用于对使用Application.Current.Dispatcher的所有公共方法进行单元测试。

I receive the following error when executing a unit test on myClass: 在myClass上执行单元测试时,我收到以下错误:

Constructor on type 'MyAssembly.MyClassInTheAssembly' not found. 找不到类型为'MyAssembly.MyClassInTheAssembly'的构造方法。

This error is generated while invoking domain.CreateInstanceFromAndUnwrap() method to create an instance of my test class. 调用domain.CreateInstanceFromAndUnwrap()方法创建我的测试类的实例时,会生成此错误。

MyClassInTheAssembly constructor has two required parameters. MyClassInTheAssembly构造函数具有两个必需的参数。 Is it possible to create an AppDomain instance of a class with parameters? 是否可以使用参数创建类的AppDomain实例?

UPDATE Thanks to user779967 for pointing me in the right direction. 更新感谢user779967为我指出了正确的方向。 The answer to my question above is to use a method override for AppDomain.CreateInstanceFromAndUnwrap(). 我上面的问题的答案是对AppDomain.CreateInstanceFromAndUnwrap()使用方法重写。 I tried using the method override to create an instance of my test class using AppDomain: 我尝试使用方法重写使用AppDomain创建测试类的实例:

        object[] parameters = new object[2];  // object array to pass my required parameters.
        parameters[0] = container;  // Required constructor param for myClass.
        parameters[1] = eventAggregator;  // Required constructor param for myClass.
        myClass = (MyClassInTheAssembly)domain.CreateInstanceFromAndUnwrap(path, typeof(MyClassInTheAssembly).FullName, true, BindingFlags.Default, null, parameters, null, null);

The idea was to use this method override to pass my required parameters to the instantiation of my test class. 想法是使用此方法重写将所需的参数传递给测试类的实例化。 Then I could use the test class derived from AppDomain which provides a dispatcher thread for all my unit tests. 然后,我可以使用派生自AppDomain的测试类,该类为我的所有单元测试提供了一个调度程序线程。

I received the following SerializationException when executing this code: Type is not resolved for member 'Castle.DynamicProxy.Serialization.ProxyObjectReference,NSubstitute, Version=1.6.1.0, Culture=neutral, PublicKeyToken=92dd2e9066daa5ca'. 执行此代码时,我收到以下SerializationException:成员'Castle.DynamicProxy.Serialization.ProxyObjectReference,NSubstitute,版本= 1.6.1.0,Culture = neutral,PublicKeyToken = 92dd2e9066daa5ca'的类型未解析。 This is because I am required to use NSubstitute for unit testing my container and eventaggregator classes. 这是因为我需要使用NSubstitute对容器和eventaggregator类进行单元测试。 The AppDomain method is looking for an exact parameter type match of IUnityContainer and IEventAggregator for my constructor parameter types, not NSubstitute. AppDomain方法正在为我的构造函数参数类型而不是NSubstitute寻找IUnityContainer和IEventAggregator的精确参数类型匹配。

I gave up my attempts to use AppDomain to instantiate my test class for unit testing. 我放弃了使用AppDomain实例化用于单元测试的测试类的尝试。 I decided to handle Application.Current within my test class method as follows: 我决定在我的测试类方法中处理Application.Current,如下所示:

        var dispatcher = Application.Current != null ? Application.Current.Dispatcher : Dispatcher.CurrentDispatcher;

        if (dispatcher.CheckAccess())
        {
            do something....
        }
        else dispatcher.Invoke(DispatcherPriority.Normal, (Action)(() => CallMethodAgain())); 

When running my code in production, Application.Current should never be null. 在生产环境中运行代码时,Application.Current绝不能为null。 When running my code for unit testing, I use Dispatcher.CurrentDispatcher to create a dispatcher from the executing thread. 在运行用于单元测试的代码时,我使用Dispatcher.CurrentDispatcher从执行线程中创建一个调度程序。

If someone out there has a nice implementation for using AppDomain to instantiate a class for unit testing, I would love to see it! 如果那里有人可以使用AppDomain实例化用于单元测试的类,那么我很乐意看到它!

Check this overloaded version of CreateInstanceAndUnwrap 检查此重载版本的CreateInstanceAndUnwrap

http://msdn.microsoft.com/en-us/library/dd387239.aspx http://msdn.microsoft.com/en-us/library/dd387239.aspx

Seems that you will need to create an array of type object[] and fill it with your constructor arguments. 似乎您需要创建一个类型为object []的数组,并用构造函数参数填充它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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