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

對於我的生活,我想不出什麼我做錯了 - 我俯瞰東西... DO我必須在模擬中設置事件的發佈事件?我應該使用真正的ItemDeletedEvent實例而不是模擬嗎?任何幫助將不勝感激。

回答

2

=>斯科特嗨,

有2視圖模型,場景,你想用一個EventAggregator何時測試:

  1. 你想測試你的視圖模型的發佈事件
  2. 你想以測試您的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

托馬斯 http://www.thomasclaudiushuber.com

+0

你當然是我根據我的代碼! :-)謝謝你的幫助,托馬斯。 –

+0

我只是沒有得到區別 - 我記得你在課程中提到它。有什麼辦法可以配置EventAggregator來做_both_嗎? –

+0

兩者都是什麼意思?問題在於發佈/訂閱邏輯不在Event聚合器中,它在Event類中。因此,爲了測試訂閱,您應該使用真實的事件類。如果您不使用真實的Event類,而是模擬,那麼您需要設置Subscribe方法並手動存儲訂閱方法並手動調用它們。 –

相關問題