2009-08-27 132 views
4

我傾向於認爲只有公共接口應該被測試,因此涵蓋私人程序的測試。然而,昨天出現了一個有趣的問題 - 應該測試一個事件處理程序嗎?我的直覺是,邏輯應該存儲在由處理程序自己調用的獨立程序中,但這是主觀的,並且很可能導致私有程序而不是正在測試的公共程序。我應該成爲單元測試事件處理程序嗎?如果是,那麼這樣做的最佳實踐是什麼?我應該單元測試事件處理程序

回答

0

我相信應該測試事件處理程序。如果你遵循的線沿線的做一些事情的正常模式:

public event EventHandler MyEvent; 
protected void OnMyEvent() 
{ 
    // Raise MyEvent here 
} 

然後MyEvent的測試實際上是OnMyEvent的測試的一部分,因爲只有「測試」,你會做的是驗證事件適當提升。

通常情況下,測試一個事件意味着訂閱它,並做一些應該(或不應該)提高它的事情。

0

我看了你的問題,並不知道你是在詢問處理程序的主體還是處理程序是否實際綁定正確來處理事件。

正如你所說,處理程序的主體應該簡單地調用另一個已經測試過的方法(如果它是公開的)。

我通常不會單元測試事件處理程序的接線,除非它們在運行時會發生變化,因爲我很可能會捕捉到我的開發人員和集成測試事件處理程序不綁定/解除綁定在運行時,沒有連接,應該是。

2

我決不會說某人對單元測試事件處理程序是「錯誤的」。就我個人而言,我會遵循「測試可能會破壞」的理念,而不會。

我見過的一貫毛病事件代碼的主要是一些單元測試不會趕上 - 「開」的方法將只是:

if (MyEventHandler != null) 
    MyEventHandler(this, e); 

這有一個競爭條件; MyEventHandler應該在空檢查之前分配給一個變量。

第二個常見錯誤是人們爲「e」事件數據參數傳遞null;這可以進行測試。

如果您沒有自己的Framework Design Guidelines 2nd Ed。 Cwalina & Abrams,現在購買。它會告訴你如何正確地編寫事件代碼,如何正確編寫Dispose模式,以及其他許多事情。

+0

那真的去了我想你說的話這麼我發佈了一些希望能夠與您所說的內容互補的內容,非常適合將此稱爲朋友,非常好! – 2012-10-05 13:06:36

0

爲了TrueWill的觀點,下面是一個很好的實現事件及其提升方法的例子。這是Microsoft的Button類的Click事件。首先要注意他們使用EventHandlerList的分配存儲在...

protected EventHandlerList Events { 
    get { 
     if (events == null) { 
      events = new EventHandlerList(this); 
     } 
     return events; 
    } 
} 

... 

public event EventHandler Click { 
    add { 
     Events.AddHandler(EventClick, value); 
    } 
    remove { 
     Events.RemoveHandler(EventClick, value); 
    } 
} 

現在注意到的實際加薪方法OnClick,它可能比你在做什麼看慣了太多不同的...

protected virtual void OnClick(EventArgs e) { 
    Contract.Requires(e != null); 
    EventHandler handler = (EventHandler)Events[EventClick]; 
    if (handler != null) handler(this, e); 
} 

...不要擔心線路Contract.Requires(e != null);,這是他們的合同管理框架,但是請注意,它將它從EventHandlerList中拉出來,然後如果該處理程序不是null,它們將會觸發它。

這裏可能值得注意的另一件事是,你可能不需要以完全相同的方式實現你的事件,但是微軟推出的編程指南實際上在這個第二部分中調用了競爭條件TrueWill指出的指南。你可以找到該指南here。這實際上是微軟的一個很好的指導。

現在,要貴點,我認爲事件應進行測試,這裏是我在過去使用的機制......

private ManualResetEvent _eventRaised = new ManualResetEvent(false); 

[TestMethod] 
public void TestSomething() 
{ 
    _eventRaised.Reset(); 

    // hook up the event to the target being tested 
    // NOW, in the event handler, issue _eventRaised.Set(); 

    // do something to raise the event 

    _eventRaised.WaitOne(); 
} 
相關問題