【问题标题】:Use AppDomain to provide application dispatcher for unit tests使用 AppDomain 为单元测试提供应用调度程序
【发布时间】:2013-08-28 18:44:19
【问题描述】:

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

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

代码示例:

        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 对我的容器和 eventtaggregator 类进行单元测试。 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 永远不应为空。在运行我的代码进行单元测试时,我使用 Dispatcher.CurrentDispatcher 从正在执行的线程创建一个调度程序。

如果有人有一个很好的使用 AppDomain 实例化类以进行单元测试的实现,我很乐意看到它!

【问题讨论】:

    标签: c# unit-testing


    【解决方案1】:

    检查 CreateInstanceAndUnwrap 的重载版本

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

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

    【讨论】:

    • 非常感谢。这个提示为我指明了正确的方向。在我原来的问题中查看我的更新。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-02-12
    • 2014-06-20
    • 2019-07-05
    • 2011-12-26
    • 1970-01-01
    • 2022-08-05
    • 2020-06-28
    相关资源
    最近更新 更多