2016-04-24 91 views
0

我有一个Autofac DI容器定义如下:为什么我的EventAggregator订阅处理此事件?

public class Bootstrapper 
{ 
    public IContainer BootStrap() 
    { 
     var builder = new ContainerBuilder(); 
     builder.RegisterType<ItemViewModel>().AsSelf(); 
     builder.RegisterType<EventAggregator>() 
      .As<IEventAggregator>() 
      .SingleInstance(); 
    } 
} 

我定义了测试的缺失是否从集合中删除已删除的项目单元测试:

[Fact] 
public void Should_remove_item_from_collection_when_item_is_deleted() 
{ 
    const int deletedId = 42; 
    // adds three items to the collection 
    _openItemEditViewEvent.Publish(deletedId); 
    _openItemEditViewEvent.Publish(8); 
    _openItemEditViewEvent.Publish(9); 

// I've tried this: 
    _eventAggregatorMock.Object.GetEvent<ItemDeletedEvent>().Publish(42); 
// and alternatively, this (not at the same time): 
    _itemDeletedEventMock.Object.Publish(42); 

    Assert.Equal(2,_vm.ItemEditViewModels.Count); // always fails 
    Assert.False(_vm.ItemEditViewModels 
    .Select(vm => vm.Item.Id).Contains(42), "Wrong item deleted"); 
} 

该股的构造测试初始化​​并将EventAggregator分配给视图模型:

_eventAggregatorMock = new Mock<IEventAggregator>(); 

_itemDeletedEventMock = new Mock<ItemDeletedEvent>(); 
_eventAggregatorMock.Setup(ea => ea.GetEvent<ItemDeletedEvent>()) 
    .Returns(_itemDeletedEventMock.Object); 

_vm = new ItemViewModel(_eventAggregatorMock.Object, */ ... /*); 

在我的实际视图模型中,我订阅活动:

public ItemViewModel(IEventAggregator ea, /* ... */) 
{ 
    _eventAggregator.GetEvent<ItemDeletedEvent>() 
     .Subscribe(OnItemDeleted, true); 
} 

,我们从来没有在这里打一个断点:

public void OnItemDeleted() 
{ 
    // never happens 
} 

对于我的生活,我想不出什么我做错了 - 我俯瞰东西... DO我必须在模拟中设置事件的发布事件?我应该使用真正的ItemDeletedEvent实例而不是模拟吗?任何帮助将不胜感激。

回答

2

=>斯科特嗨,

有2视图模型,场景,你想用一个EventAggregator何时测试:

  1. 你想测试你的视图模型的发布事件
  2. 你想以测试您的ViewModel在事件发布时做了些什么。因此视图模型具有订阅该事件做一些

(注:以下线是PRISM的EventAggregator,这是你使用我想一个真正的对于其他EventAggregators也可能是不同的。)

对于第一种情况,您必须为事件创建一个模拟。然后,您可以在该模拟实例上验证事件的发布方法已被调用。

对于第二种情况,这是您的问题中的场景,您必须在测试中使用真实的事件。为什么?

  • 当您在事件模拟中调用发布方法时,该发布方法将不会调用该事件的订阅者,因为订阅方法背后没有任何逻辑。当然,你可以设置这两种方法,并在你的模拟中实现发布/订阅逻辑。但是没有理由这样做,只需使用真实事件
  • 当您使用真实事件时,发布方法将调用所有订阅者。这正是你在测试中需要的东西。

它应该是这样的:

_itemDeletedEvent = new ItemDeletedEvent(); 
_eventAggregatorMock.Setup(ea => ea.GetEvent<ItemDeletedEvent>()) 
    .Returns(_itemDeletedEvent); 

现在您的视图模型将得到来自EventAggregator这itemDeletedEvent实例。在你的测试中,你调用了这个itemDeletedEvent-instance上的Publish-method,它会起作用。

更多关于这在我的课程说明在Pluralsight约WPF和测试驱动开发:http://www.pluralsight.com/courses/wpf-mvvm-test-driven-development-viewmodels

托马斯 http://www.thomasclaudiushuber.com

+0

你当然是我根据我的代码! :-)谢谢你的帮助,托马斯。 –

+0

我只是没有得到区别 - 我记得你在课程中提到它。有什么办法可以配置EventAggregator来做_both_吗? –

+0

两者都是什么意思?问题在于发布/订阅逻辑不在Event聚合器中,它在Event类中。因此,为了测试订阅,您应该使用真实的事件类。如果您不使用真实的Event类,而是模拟,那么您需要设置Subscribe方法并手动存储订阅方法并手动调用它们。 –

相关问题