2009-09-22 14 views
1

我想測試我的類如何對BackgroundWorker觸發RunWorkerCompleted事件時發生的情況做出反應。如何在嘲笑的BackgroundWorker上引發事件?

我使用RhinoMocks(如果有另一種方法,我願意去嘗試它),代碼如下:

//arrange 
var bw1 = MockRepository.GenerateStub<BackgroundWorker>(); 
Action work1 =() => Thread.Sleep(1); 
WorkQueueProcess processInQueue = new WorkQueueProcess(bw1) { Work = work1 }; 
var tested = new WorkQueue() { processInQueue }; 

// act 
bw1.Raise(
    bw => bw.RunWorkerCompleted += 
     null, 
     bw1, 
     new RunWorkerCompletedEventArgs(null, null, false) 
); 

// assert 
Assert.AreEqual(false, tested.IsBusy); 

我得到的是說,一個例外:

無效的調用,最後調用一直使用 或者沒有來電的情況下(讓 確保您調用虛 (C#)/可重寫(VB)方法)。

我在做什麼錯?是否因爲BackgroundWorker沒有虛擬方法?我認爲我應該能夠提出一個事件,因爲事件幾乎不是虛擬的。

回答

1

只有定義了一個事件可以提高該事件的類。這就是.NET中事件系統的工作原理。

由RhinoMocks提供高揚方法的目的是與定義的事件的接口中使用。在這種情況下,實現該接口的任何類都擁有自己的事件,因此能夠提升它。對於由RhinoMocks生成的運行時間發射類型也是如此。

然而,當涉及到類,甚至子類型不能提高通過超類型定義的事件,這就是爲什麼我們有一個OnEvent編碼成語。

BackgroundWorker的確實有,這將引發該事件的OnRunWorkerCompleted方法。這個方法是虛擬的,所以如果你可以讓RhinoMocks調用這個受保護的方法,你應該能夠引發這個事件。

我正在使用Moq,其中不能這樣做 - 我不記得RhinoMocks是否有能力調用受保護的成員。

否則,你可以得到從BackgroundWorker的特定測試類,並添加調用OnRunWorkerCompleted的公共方法。

由於關閉的話,但是,我會強烈建議您不要嘗試單元測試多線程的代碼 - 沿這條道路只在於疼痛...

+0

非常感謝你提醒我的成語( OnEvent的成語)我還沒有想到,雖然我以前遇到過這個。 RhinoMocks似乎無法調用受保護的成員,但創建我自己的後臺工作者模擬似乎可以完成這項工作。 我想測試我的對象是否會對後臺工作者結果做出正確反應,我甚至不會嘗試多線程單元測試。感謝您的警告。 – 2009-09-23 08:04:15