2014-01-21 93 views
2

我想寫一個單元測試使用JustMock忽略事件。試圖單元測試一個事件與JustMock

我做不是想測試事件本身,因爲它調用各種內部函數,這將需要大量的模擬工作。

下面是示例代碼的快速位:

public class Sample 
{ 
    public delegate void OneParameterFunction(int someVar); 
    public event OneParameterFunction TheEvent;    

    public Sample() 
    {    
     TheEvent += CallMe; 
    } 

    public void CallMe(int someVar) 
    { 
     Debug.WriteLine("CallMe was fired with parameter: " + someVar); 
    } 

    public void FireEvent() 
    { 
     // do stuff, business logic here... 
     if (TheEvent != null) 
      TheEvent(3); 
    } 
} 

這裏是測試我會來寫,但不能:

[TestClass] 
class EventMocking 
{ 
    [TestMethod] 
    public void DoNothingOnEvent() 
    { 
     var s = new Sample(); 

     Mock.Arrange(() => s.TheEvent(Arg.AnyInt))    
      .DoNothing(); 

     Mock.Arrange(() => s.CallMe(Arg.AnyInt)) 
      .OccursNever(); 

     s.FireEvent(); 

     Mock.Assert(() => s.CallMe(Arg.AnyInt)); 
    } 
} 

但我收到以下編譯器錯誤:

Error 1 The event 'Sample.TheEvent' can only appear on the left hand side of += or -= (except when used from within the type 'Sample') C:\BizObjectTests\EventMocking.cs 

有沒有人有任何建議如何阻止事件傳播?我也不想Mock.Create<T>由於多種原因,其中一個是我再次必須設置更多的測試數據/對象。

回答

1

由於它是由JIT內部實現的,所以不可能模擬委託調用本身。

你有幾個備選方案。如果您使用專用於此目的的方法提升事件(如您的示例),那麼您可以簡單地嘲笑該方法。所以,你的樣本中就變成了:

Mock.Arrange(() => s.FireEvent()).DoNothing(); 

如果這是不可能的,那麼你可以嘲笑,增加了處理該事件的方法(在一個叫當樣品+ = ...被調用)。你可以這樣做,像這樣:

var mock = Mock.Create<Sample>(); // we need this just for the following arrangement 
Mock.ArrangeSet(() => mock.TheEvent += null).IgnoreInstance().IgnoreArguments().DoNothing(); 

var real = new Sample(); // TheEvent += CallMe will now do nothing 
real.FireEvent(); // TheEvent is empty 

最後,作爲第三個選擇,你可以從事件中使用反射在某些時候刪除所有處理程序,你知道事件只是將被解僱,或者說沒有人否則將附加到它:

new PrivateAccessor(real).SetField("TheEvent", null); 
real.FireEvent(); // TheEvent is null right now 

警告:這最後的選擇是依賴於編譯器實現。它將用於C#代碼中的事件聲明,但不適用於VB事件。