2011-09-19 48 views
7

我寫單元測試,並試圖提高從抽象類模擬事件時收到異常接口中聲明的事件。下面是示例代碼:C#和起訂量,提高從抽象類模擬

public abstract class AbstractBase : EntityObject 
    {} 

    [TestMethod] 
    public void MyTest() 
    { 

     var mock = new Mock<AbstractBase>(); 
     var notificationMock = entityMock.As<INotifyPropertyChanged>(); 

     var propertyChangedMapper = new PropertyChangedMapper(); 

     bool eventReceived = false; 
     propertyChangedMapper.MyPropertyChanged += 
      (sender, eventArgs) => 
       { 
        eventReceived = true; 
       }; 

     propertyChangedMapper.Subscribe((AbstractBase)notificationMock.Object); 

     Assert.IsFalse(eventReceived); 

     notificationMock.Raise(e=>e.PropertyChanged += null, 
            new PropertyChangedEventArgs("Property1")); 

     Assert.IsTrue(eventReceived); 
    } 

很顯然,我可以在INotifyPropertyChanged使用模擬和事件復活了就好了,但PropertyChangedMapper裏面我需要的,如果使用Mock<INotifyPropertyChanged>

編輯給發件人轉換爲AbstractBase它失敗: 按使用Mock.As<>()建議似乎是正確的方式去,唯一的問題是上面從notificationMock上升事件無關與對象的原始模擬。代碼:

 notificationMock.Object.PropertyChanged += (s, e) => 
     { 
      var result = "this one is fired as it should"; 
     }; 

     mock.Object.PropertyChanged += (s, e) => 
     { 
      var result = "this one is not called but is actually what I need"; 
     }; 

     notificationMock.Raise(e => e.PropertyChanged += null, 
       new PropertyChangedEventArgs("Property1")); 
+0

只要有人打電話,不管它叫哪一個。我的猜測是你可以設置其中一個或另一個。但建立兩者都會導致模擬內部選擇一個。 –

+0

欲瞭解更多證明,不要緊被稱爲,認爲類型系統的工作方式類似於虛擬成員和他們的覆蓋。例如,如果您添加到AbstractBase爲EntityObject的INPC事件的覆蓋,是沒有辦法的任何代碼消耗AbstractBase強制EntityObject的版本被調用。即使您投射到EntityObject,也會調用AbstractBase成員。一旦基礎成員被覆蓋,只有派生類可以訪問原始基礎成員。 –

回答

1

您可能能夠做到所期望的投如果你讓你模擬一個MULT-模擬。由於起訂量嘲笑通過通用參數綁定到一個單獨的類型,你必須明確地逐步增加額外的接口或超類來模擬,然後用高端產品在您的測試。下面是一個簡單的例子。

var baseMock = new Mock<AbstractBase>(); 
var inpcMock = baseMock.As<INotifyPropertyChanged>(); 

// ...setup event... 

propertyChangedMapper.Subscribe(inpcMock.Object); 

// ... assertions ... 
+1

偉大的功能!然而,它看起來事件不是通過'inpcMock.Raise(e => e。PropertyChanged + = null,新的PropertyChangedEventArgs(「Property1」));' - 任何想法爲什麼? – Paul

+0

請參閱上面的更新 – Paul

1

鑑於你這樣做的方式,沒有活動的實施。接口本身只是說「我有一個PropertyChanged事件」的合同。如果你想提出這個事件,你必須提供一個處理程序,即使它沒有做任何事情。在你的模擬類中實現PropertyChanged事件來引發事件。

UPDATE:

試試這個代碼,您AbstractBase:

public abstract class AbstractBase : INotifyPropertyChanged 
{ 
    public virtual event PropertyChangedEventHandler PropertyChanged; 
    private void NotifyPropertyChanged(String info) 
    { 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(info)); 
     } 
    } 
} 
+0

那麼究竟應該做什麼來解決這個異常? – Paul

+1

由於像「公共抽象類AbstractBase:INotifyPropertyChanged {}」的代碼無法編譯,我認爲他只是縮短了這裏的代碼... – David

+0

@Paul:查看更新。 –

1

是您聲明爲virtual事件PropertyChanged事件?

public abstract class AbstractBase : INotifyPropertyChanged 
{ 
    public virtual event PropertyChangedEventHandler PropertyChanged; 
} 

(參見:Jon Skeet on virtual events

+0

請參閱上面的編輯 – Paul

+0

我想我不清楚這個問題。你原來的代碼對我來說工作得很好(沒有所有的'As <>()'東西)。 – ladenedge

+0

使事件虛擬工作過,但只有當這是我的類,它實現的事件。當從已經有實現的基類繼承時 - 無法使事件變爲虛擬。感謝您的回答。 – Paul