2016-04-24 1 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 
} 

Для жизни меня, я не могу понять, что я делаю неправильно - я что-то с видом ... не Мне нужно настроить событие публикации в Mock? Должен ли я использовать реальный экземпляр ItemDeletedEvent вместо Mock? Любая помощь будет принята с благодарностью.

ответ

2

=> Привет Скотт,

есть 2 ViewModel-сценарий вы хотите проверить при использовании EventAggregator:

  1. Вы хотите проверить, что ваш ViewModel публикует событие
  2. Вы хотите чтобы проверить, что ваш ViewModel что-то делает, когда было опубликовано событие. Так ViewModel должен подписаться на это событие, чтобы сделать что-то

(Примечание: Следующие строки справедливы для EventAggregator Prism, который является тот, который вы используете, я думаю, для других EventAggregators это может быть по-другому.)

Для первого сценария вам необходимо создать макет для события. Затем вы можете проверить этот макет-экземпляр, который был вызван методом публикации-публикации.

Для второго сценария, который является сценарием, который у вас есть в вашем вопросе, вы должны использовать реальное событие в своем тесте. Зачем?

  • Когда вы вызываете метод Publish для события-макета, этот метод публикации не будет вызывать подписчиков на это событие, так как для метода Subscribe нет никакой логики. Конечно, вы можете настроить оба метода и реализовать эту публикацию/подписку-логику в своем макете. Но нет причин для этого, просто используйте реальное событие
  • Когда вы используете реальное событие, метод Publish вызовет всех подписчиков. И это именно то, что вам нужно в вашем тесте.

Он должен выглядеть следующим образом:

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

Теперь ваш ViewModel получит этот itemDeletedEvent-экземпляр из EventAggregator. В вашем тесте вы вызываете метод Publish в этом элементе itemDeletedEvent-экземпляре, и он будет работать.

Подробнее об этом объясняется в моем курсе по Pluralsight о WPF и Test Driven Development: http://www.pluralsight.com/courses/wpf-mvvm-test-driven-development-viewmodels

Томас http://www.thomasclaudiushuber.com

+0

Ваш курс, что я на основе моего кода на! :-) Спасибо за помощь, Томас. –

+0

Я просто не получал различие - я помню, вы упомянули об этом в курсе. Есть ли способ настроить EventAggregator на выполнение _both_? –

+0

Что вы подразумеваете под этим? Проблема заключается в том, что логика публикации/подписки отсутствует в агрегаторе Event, она находится в классе Event. Поэтому для тестирования подписки вы должны использовать реальный класс событий. Если вы не используете настоящий класс Event, но макет, вам нужно установить метод Subscribe и сохранить методы подписки вручную и вызвать их вручную. –

 Смежные вопросы

  • Нет связанных вопросов^_^