【发布时间】:2016-05-06 19:44:54
【问题描述】:
我正在使用 Moq、xUnit 和 Prism 4。我的单元测试的目标是触发一个事件并确认我的视图模型中的某个属性已更改以匹配来自该事件的值。顺便说一句,这个测试失败了(预期:5,实际:0):
// Version One
[Fact]
public void Should_set_DayCount_on_DayCountChangedEvent()
{
var eaMock = new Mock<IEventAggregator>();
eaMock.SetupCurriculumEvents(); // see below
var vm = new CurriculumItemViewModel(eaMock.Object, _systemStatus.Object);
vm.Load(_newItem);
var dayCount = 5;
eaMock.Object.GetEvent<DayCountChangedNotification>().Publish(dayCount);
Assert.Equal(dayCount, _vm.DayCount);
}
我厌倦了到处设置我的事件聚合器模拟,所以我创建了一个扩展方法来为我完成繁琐的工作:
public static void SetupCurriculumEvents(this Mock<IEventAggregator> eaMock)
{
eaMock.Setup(ea => ea.GetEvent<DayCountChangedNotification>())
.Returns(new DayCountChangedNotification());
// lots of other "notification" events here as well
}
然后我意识到,每次从模拟事件聚合器中检索到新事件时,我都会创建一个新事件,因此一个实例(在 VM 中)上的 Subscribe() 与 Publish(dayCount) 不在同一个实例上我的测试。
好吧,我想,让我们始终使用同一个对象(通过覆盖扩展方法的 Setup() 来处理此事件),我们会做得很好:
// Version Two
[Fact]
public void Should_set_DayCount_on_DayCountChangedEvent()
{
var dayCountChangedEvent = new DayCountChangedNotification();
var eaMock = new Mock<IEventAggregator>();
eaMock.SetupCurriculumEvents(); // still need this for all the other events
// overwrite the setup from the extension method
eaMock.Setup(ea => ea.GetEvent<DayCountChangedNotification>())
.Returns(dayCountChangedEvent);
var vm = new CurriculumItemViewModel(eaMock.Object, _systemStatus.Object);
vm.Load(_newItem);
var dayCount = 5;
dayCountChangedEvent.Publish(dayCount);
Assert.Equal(dayCount, _vm.DayCount);
}
...这也失败了。
出于某种原因,我决定尝试重构扩展方法,(并将单元测试恢复为版本一):
public static class MockingExtensions
{
private static DayCountChangedNotification DayNotification = new DayCountChangedNotification();
public static void SetupCurriculumEvents(this Mock<IEventAggregator> eaMock)
{
eaMock.Setup(ea => ea.GetEvent<DayCountChangedNotification>())
.Returns(DayNotification);
// etc...
}
}
...在我看来,基本上是一样的——我总是返回相同的事件实例。
这是关键:这个测试通过了。
这很好,一切都很好,但我不明白为什么它会通过 - 如果我不明白它为什么会通过,那么我真的不知道它是否正确。
接受的答案需要解释两件事:
- 为什么用静态实例重构的扩展方法通过了?
- 为什么第二版没有通过?
【问题讨论】:
-
声明静态类字段与局部变量不同。您是仅运行此测试还是在与其他测试一起运行时运行此测试? DayCountChangedNotification 的实现是什么?
-
DayCountChangedNotification只是一个空类,它继承自 Prism 的CompositePresentationEvent<int?>类。该测试既可以单独运行,也可以与其他测试联合运行 - 结果是一致的。
标签: unit-testing moq xunit prism-4