使用分派器时的单元测试CompositePresentationEvent [英] Unit Testing CompositePresentationEvent when using the Dispatcher

查看:152
本文介绍了使用分派器时的单元测试CompositePresentationEvent的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用Prism / Composite应用程序库,并尝试对使用EventAggregator订阅CompositePresentationEvent的某些代码进行单元测试。引发事件的代码将其引发到另一个线程上,因此我使用ThreadOption.UIThread订阅了该事件。

Im using the Prism/Composite Application Library and trying to unit test some code that subscribes to a CompositePresentationEvent using the EventAggregator. The code that is raising the event is raising it on another thread so I am subscribing to the event using ThreadOption.UIThread.

当事件引发回调时,它将使用应用程序将其放置到UI线程上的调度程序。这在正常执行期间很好,但是在单元测试期间没有调度程序。 CompositePresentationEvent中的代码如下:

When the event raises the callback it uses the application dispatcher to put it onto the UI thread. This is fine during normal execution but during a unit test there is no dispatcher. The code in CompositePresentationEvent looks like this:

    private IDispatcherFacade UIDispatcher
    {
        get
        {
            if (uiDispatcher == null)
            {
                this.uiDispatcher = new DefaultDispatcher();
            }

            return uiDispatcher;
        }
    }



public class DefaultDispatcher : IDispatcherFacade
{
    /// <summary>
    /// Forwards the BeginInvoke to the current application's <see cref="Dispatcher"/>.
    /// </summary>
    /// <param name="method">Method to be invoked.</param>
    /// <param name="arg">Arguments to pass to the invoked method.</param>
    public void BeginInvoke(Delegate method, object arg)
    {
        if (Application.Current != null)
        {
            Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Normal, method, arg);
        }
    }
}

问题在于CompositePresentationEvent是与DefaultDispatcher绑定,如果没有应用程序在运行,此调度程序将不执行任何操作。

The problem being that CompositePresentationEvent is tied to the DefaultDispatcher, and this dispatcher does nothing if there is no Application running.

在这种情况下,是否有人进行过成功的单元测试?有什么技巧或变通方法可以使调度员发挥作用?

Has anyone had any success unit testing in this kind of situation? Any tips or workarounds to kick the dispatcher into life?

我知道我可以将回调函数设置为内部,并允许单元测试调用此方法,但是我不希望更改

I know I could make my callback internal and allow my unit test to call this method but I would prefer not to change my code and leave this approach as a last resort.

推荐答案

您没有发布测试,所以我不清楚您正在尝试测试,但是最有可能的是,您正在尝试测试以下其中一项:

You didn't post your tests, so I'm unclear what you are trying to test, but most-likely you are trying to test one of the following things:


  1. 您正在测试的代码已订阅根本

  2. 正在测试的代码对事件做出适当反应

您将要模拟EventAggregator 。由于该事件不是您要测试的东西,而是要利用它的代码,因此,您想提供一种伪造的替代品来完成您想要的工作。我会尝试提供一个很好的例子。我使用Moq,但是您可以选择任何喜欢的模拟框架。

In either case, you are going to want to mock the EventAggregator. Because the Event isn't what you want to test, but rather the code that utilizes it, you want to provide a fake alternative that does what you want it to do. I'll try and provide a good example. I use Moq, but you can choose whatever mocking framework you like.

在此测试中,我只断言在构造函数中调用了Subscribe,但是您的测试可能更多。如果要测试类对引发事件的反应,则非常复杂。测试显示 CompositePresentationEvent< int>

In this test, I simply assert that Subscribe was called in the constructor, but your test might be more complicated if you are wanting to test the class's reaction to a raised event. The test shows a CompositePresentationEvent<int>.

//Arrange
Mock<MyEvent> mockEvent = new Mock<MyEvent>();
Mock<IEventAggregator> mockAggregator = new Mock<IEventAggregator>();

mockEvent.Setup
(
     evnt => evnt.Subscribe(It.IsAny<Action<int>>())
);
mockAggregator.Setup
(
    agg => agg.GetEvent<MyEvent>()
              .Returns(mockEvent.Object);
);

//Act
MyClassIWantToTest target = new MyClassIWantToTest(mockAggregator.Object);

//Assert
mockEvent.VerifyAll();

这是基本知识。经验法则是,如果测试依赖于难以提供的系统资源,请将其与测试隔离。

That's the basics. The rule of thumb here is that if you tests rely on a system resource that is difficult to provide, isolate it from the test.

编辑:在阅读完您的问题,我看到您正在尝试测试回调。

在此示例中,我测试是否将 CurrentValueProperty属性设置为传入的任何值回调方法。这是该示例:

In this sample, I test if the "CurrentValueProperty" property is set to whatever value is passed in the callback method. Here is that sample:

//Arrange
Mock<MyEvent> mockEvent = new Mock<MyEvent>();
Mock<IEventAggregator> mockAggregator = new Mock<IEventAggregator>();
Action<int> theEventCallback = null;

mockEvent.Setup
(
    evnt => evnt.Subscribe(It.IsAny<Action<int>>())
)
.Callback<Action<int>>
(
    cb => theEventCallback = cb
);


mockAggregator.Setup
(
    agg => agg.GetEvent<MyEvent>()
)
.Returns(mockEvent.Object);

//Act
MyClassIWantToTest target = new MyClassIWantToTest(mockAggregator.Object);

//we expect this to be populated by the callback specified in our mock setup
//that will be triggered when Subscribe is called in 
//MyClassIWantToTest's constructor
theEventCallback(27);

//Assert
Assert.AreEqual(target.CurrentValueProperty, 27);

就是这样。

这篇关于使用分派器时的单元测试CompositePresentationEvent的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆