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

时间:2013-08-28 18:44:20

标签: c# unit-testing

问题:运行单元测试时,Application.Current在类中为null。

解决方法:创建将运行我的测试类的应用程序域。应用程序域将为我的测试类提供调度程序。

代码示例:

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

myClass对象可用于对使用Application.Current.Dispatcher的任何公共方法进行单元测试。

在myClass上执行单元测试时收到以下错误:

未找到类型'MyAssembly.MyClassInTheAssembly'的构造函数。

在调用domain.CreateInstanceFromAndUnwrap()方法时会生成此错误,以创建我的测试类的实例。

MyClassInTheAssembly构造函数有两个必需参数。是否可以使用参数创建类的AppDomain实例?

更新 的 感谢user779967让我指向了正确的方向。我上面的问题的答案是使用AppDomain.CreateInstanceFromAndUnwrap()的方法覆盖。 我尝试使用方法覆盖来使用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);

我的想法是使用此方法覆盖将我所需的参数传递给我的测试类的实例化。然后我可以使用从AppDomain派生的测试类,它为我的所有单元测试提供调度程序线程。

执行此代码时收到以下SerializationException:成员'Castle.DynamicProxy.Serialization.ProxyObjectReference,NSubstitute,Version = 1.6.1.0,Culture = neutral,PublicKeyToken = 92dd2e9066daa5ca'的类型未解析。这是因为我需要使用NSubstitute对我的容器和eventaggregator类进行单元测试。 AppDomain方法正在为我的构造函数参数类型寻找IUnityContainer和IEventAggregator的精确参数类型匹配,而不是NSubstitute。

我放弃了尝试使用AppDomain实例化我的测试类进行单元测试的尝试。我决定在我的测试类方法中处理Application.Current,如下所示:

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

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

在生产中运行我的代码时,Application.Current永远不应为null。运行我的代码进行单元测试时,我使用Dispatcher.CurrentDispatcher从正在执行的线程创建一个调度程序。

如果那里有人使用AppDomain实例化单元测试类,我很乐意看到它!

1 个答案:

答案 0 :(得分:0)

检查CreateInstanceAndUnwrap

的这个重载版本

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

似乎您需要创建一个object []类型的数组,并用构造函数参数填充它。