Search code examples
c#tddprismui-threadeventaggregator

How do I test Prism event aggregator subscriptions, on the UIThread?


I have a class, that subscribes to an event via PRISMs event aggregator.

As it is somewhat hard to mock the event aggregator as noted here, I just instantiate a real one and pass it to the system under test.

In my test I then publish the event via that aggregator and then check how my system under test reacts to it. Since the event will be raised by a FileSystemWatcher during production, I want to make use of the automatic dispatch by subscribing on the UIThread, so I can update my UI once the event is raised.

The problem is, that during the test, the event never gets noticed in the system under test unless I don't subscribe on the UIThread.

I am using MSpec for my tests, which I run from inside VS2008 via TDD.Net. Adding [RequiresSta] to my test class didn't help

Does anyone have a solution, that saves me from changing the ThreadOption during my tests (e.g. via a property - what an ugly hack)???


Solution

  • If you mock both the event and the Event Aggregator, and use moq's Callback, you can do it.

    Here's an example:

    Mock<IEventAggregator> mockEventAggregator;
    Mock<MyEvent> mockEvent;
    
    mockEventAggregator.Setup(e => e.GetEvent<MyEvent>()).Returns(mockEvent.Object);
    
    // Get a copy of the callback so we can "Publish" the data
    Action<MyEventArgs> callback = null;
    
    mockEvent.Setup(
        p =>
        p.Subscribe(
            It.IsAny<Action<MyEventArgs>>(), 
            It.IsAny<ThreadOption>(), 
            It.IsAny<bool>(), 
            It.IsAny<Predicate<MyEventArgs>>()))
            .Callback<Action<MyEventArgs>, ThreadOption, bool, Predicate<MyEventArgs>>(
            (e, t, b, a) => callback = e);
    
    
    // Do what you need to do to get it to subscribe
    
    // Callback should now contain the callback to your event handler
    // Which will allow you to invoke the callback on the test's thread
    // instead of the UI thread
    callback.Invoke(new MyEventArgs(someObject));
    
    // Assert