为什么我的EventAggregator订阅处理此事件?
问题描述:
我有一个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视图模型,场景,你想用一个EventAggregator何时测试:
- 你想测试你的视图模型的发布事件
- 你想以测试您的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
你当然是我根据我的代码! :-)谢谢你的帮助,托马斯。 –
我只是没有得到区别 - 我记得你在课程中提到它。有什么办法可以配置EventAggregator来做_both_吗? –
两者都是什么意思?问题在于发布/订阅逻辑不在Event聚合器中,它在Event类中。因此,为了测试订阅,您应该使用真实的事件类。如果您不使用真实的Event类,而是模拟,那么您需要设置Subscribe方法并手动存储订阅方法并手动调用它们。 –