Я использую 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
}
Затем я понял, что создаю новое событие каждый раз, когда оно извлекается из агрегатора фиктивных событий, поэтому 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
— это просто пустой класс, наследуемый от классаCompositePresentationEvent<int?>
Prism. Тест выполнялся как в одиночку, так и совместно с другими тестами — результаты были одинаковыми. - person Scott Baker   schedule 09.05.2016