Rhino Mocks and PRISM EventAggregator
I need to do something that seems quite simple, but I cant seem to achieve it.
I need to be able to write a unit test that calls the action and filter delegates of any subscription to an eventaggregator event.
For example, in my class that needs to be tested I have the following code:
this.eventAggregator.GetEvent<RiskDataViewsJournalChangedEvent>().Subscribe(
this.OnViewRequestPublished, ThreadOption.UIThread, false, this.EventFilter);
and I want my test to call the this.OnViewRequestPublished
method and this.EventFilter
method.
Ive tried using an instance of the EventAggregator
class in开发者_开发知识库 my test but the events never get fired without a dispatcher present, which is not helpfull in a unit test.
Therefore I want to use Rhino Mocks, but I cant get my head around how to achieve what I need.
Thanks
Dean
Ive solved it myself - here is my code (ignore the EventToken
references, this is something ive created myself for event filtering).
[Test]
public void RiskDataGridViewModelEventSubscriptionTests()
{
// event token
var tok = new EventToken();
// mock event aggregator
var agg = MockRepository.GenerateStub<IEventAggregator>();
// my target class subscribes to 3 events in its constructor
var evt1 = MockRepository.GenerateStub<RiskDataViewsJournalChangedEvent>();
var evt2 = MockRepository.GenerateStub<RiskDataViewsJournalChangingEvent>();
var evt3 = MockRepository.GenerateStub<RiskDataViewRequestPublishEvent>();
// ensure mocked event classes are returned
agg.Stub(x => x.GetEvent<RiskDataViewsJournalChangedEvent>()).Return(evt1);
agg.Stub(x => x.GetEvent<RiskDataViewsJournalChangingEvent>()).Return(evt2);
agg.Stub(x => x.GetEvent<RiskDataViewRequestPublishEvent>()).Return(evt3);
// instantiate target class - in my class the events get subscribed to in the constructor
new RiskDataGridViewModel(agg, tok, null);
// get the parameters passed to the subscribe method
var args1 = evt1.GetArgumentsForCallsMadeOn(s => s.Subscribe(null));
var args2 = evt2.GetArgumentsForCallsMadeOn(s => s.Subscribe(null));
var args3 = evt3.GetArgumentsForCallsMadeOn(s => s.Subscribe(null));
// invoke filters
((Predicate<EventParameter<IRiskDataViewResultItem>>)args1[0][3]).Invoke(new EventParameter<IRiskDataViewResultItem>(null, tok));
((Predicate<EventParameter>)args2[0][3]).Invoke(new EventParameter(null, tok));
((Predicate<EventParameter<ViewRequest>>)args3[0][3]).Invoke(new EventParameter<ViewRequest>(null, tok));
// invoke methods
((Action<EventParameter<IRiskDataViewResultItem>>)args1[0][0]).Invoke(new EventParameter<IRiskDataViewResultItem>(null, tok));
((Action<EventParameter>)args2[0][0]).Invoke(new EventParameter(null, tok));
((Action<EventParameter<ViewRequest>>)args3[0][0]).Invoke(new EventParameter<ViewRequest>(null, tok));
}
/// <remarks>Event.Publish does not work in unit tests when subscribed with ThreadOption.UIThread </remarks>
public void FireGlobalEvent<TEvent, TEventArgs>(TEventArgs args)
where TEvent : CompositePresentationEvent<TEventArgs>, new ()
{
var globalEvent = GetInstance<IEventAggregator>().GetEvent<TEvent>();
var subscriptions = (IEnumerable)globalEvent.GetType().GetProperty("Subscriptions", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(globalEvent);
foreach (DispatcherEventSubscription<TEventArgs> subscription in subscriptions.Cast<object>().ToArray())
{
subscription.Action.Invoke(args);
}
}
精彩评论