gpt4 book ai didi

unit-testing - 为什么我的EventAggregator订阅不处理此事件?

转载 作者:行者123 更新时间:2023-12-03 10:22:37 26 4
gpt4 key购买 nike

我有一个定义如下的Autofac DI容器:

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分配给 View 模型:
_eventAggregatorMock = new Mock<IEventAggregator>();

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

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

在我的实际 View 模型中,我订阅了该事件:
public ItemViewModel(IEventAggregator ea, /* ... */)
{
_eventAggregator.GetEvent<ItemDeletedEvent>()
.Subscribe(OnItemDeleted, true);
}

而且我们在这里从未遇到过断点:
public void OnItemDeleted()
{
// never happens
}

对于我的一生,我无法弄清楚自己在做什么错-我正在忽略某些事情...我是否必须在Mock中设置事件的Publish事件?我应该使用真实的ItemDeletedEvent实例而不是Mock吗?任何帮助将不胜感激。

最佳答案

=>嗨,斯科特,

使用EventAggregator时,要测试2种ViewModel场景:

  • 您想测试ViewModel正在发布事件
  • 您想测试事件发布后ViewModel是否执行了某些操作。因此,ViewModel必须订阅该事件才能执行

  • (注意:以下几行适用于PRISM的EventAggregator,我猜这是您正在使用的那行。对于其他EventAggregator,可能会有所不同)

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

    对于第二种情况,即您遇到的问题,您必须在测试中使用真实事件。为什么?
  • 当您在事件模拟中调用Publish方法时,该Publish方法将不会调用该事件的订阅者,因为Subscribe方法背后没有逻辑。当然,您可以设置这两种方法,并在您的模拟中实现该发布/订阅逻辑。但是没有理由这样做,只需使用实际的事件
  • 使用真实事件时,发布方法将调用所有订阅者。这正是您在测试中需要的。

  • 它看起来应该像这样:
    _itemDeletedEvent = new ItemDeletedEvent();
    _eventAggregatorMock.Setup(ea => ea.GetEvent<ItemDeletedEvent>())
    .Returns(_itemDeletedEvent);

    现在,您的ViewModel将从EventAggregator中获取此itemDeletedEvent-instance。在测试中,您可以对此itemDeletedEvent-instance调用Publish-method,它将起作用。

    有关此问题的更多信息,请参见我的有关WPF和测试驱动开发的Pluralsight类(class): http://www.pluralsight.com/courses/wpf-mvvm-test-driven-development-viewmodels

    汤玛士
    http://www.thomasclaudiushuber.com

    关于unit-testing - 为什么我的EventAggregator订阅不处理此事件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36818747/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com