2017-10-20 74 views
-1

嗯,我試圖創建一個測試套件來測試包含某個事件的類。基本上我希望調用一個方法,給這個方法一個事件,一段測試代碼和一個事件執行的對象,最後是事件引發的預期次數。通用事件測試方法,防止代碼複製

我的第一次迭代是:

protected void EventFireTest<T>(EventHandler theEvent, T g, TestAction<T> action) where T: class{ 
     var invokeChangedCount = 0; 

     theEvent += (sender, e) => { ++invokeChangedCount; };    

     foreach (var actionPair in action.AllActions) { 
      invokeChangedCount = 0; 
      var num = actionPair.Item2; 
      var actualAction = actionPair.Item1; 
      actualAction(g); 

      Assert.That(actual: invokeChangedCount, expression: Is.EqualTo(expected: num)); 

     } 
    } 

它會被稱爲像:

EventFireTest(obj.PropertyChanged,OBJ,行動);

其中action包含動作對以及一些元數據,如正在執行的動作的視覺線索。

但是,當我試圖將一個事件傳遞給此函數時,問題是「事件只能是+ =和 - =的lhs」。儘管這是我最終做的唯一事情。 (編譯器應該能夠從理論上檢查這個問題嗎?)

現在爲了避免這個問題,我採取了一種更爲臃腫的方法,直接引入已經不需要的代碼重複以及將內部細節泄漏到外部測試方法。通過爲EventFireTest方法提供一個lambda來執行。

 Action<int> setup = n => obj.PropertyChanged += (sender, e) => { 
      ++n; 
     }; 
     EventFireTest(setup, obj, action); 

我覺得uglyness已經是相當明顯的(突然我需要關心如何計數的事件,執行完成):

protected void EventFireTest<T>(Action<int> EventSetupAction, T g, TestAction<T> action) where T: class{ 
     var invokeChangedCount = 0; 

     EventSetupAction(invokeChangedCount); 

     foreach (var actionPair in action.AllActions) { 
      invokeChangedCount = 0; 
      var num = actionPair.Item2; 
      var actualAction = actionPair.Item1; 
      actualAction(g); 

      Assert.That(actual: invokeChangedCount, expression: Is.EqualTo(expected: num)); 

     } 
    } 

現在的代碼將被調用。但更重要的是,上面的代碼將無法工作。

代替「更改」EventFireTest中的變量,lambda創建變量的本地副本,並更新該變量。所以我需要通過引用來傳遞整數,如果沒有一些複雜的方法,這也是不可能的。

這些問題相結合使我相信我目前還沒有找到解決這個問題的正確方向。最直接的方式是什麼?

回答

-1

而不是讓你的委託取一個整數並遞增它,而是讓委託提供一個事件處理程序,並讓委託的主體將該事件處理程序添加到事件中。這使得來電者:

Action<EventHandler> setup = handler => obj.PropertyChanged += handler; 
EventFireTest(setup, obj, action); 

對於你現在只需要把你在原來的版本寫的處理程序,並將其作爲參數傳遞給該操作的測試方法。

解決問題的另一種方法是將T限制爲實現某個接口的類型,其中接口定義了您需要訂閱的事件。如果所有這個測試的調用者在邏輯上測試一個特定類型的事件,而不是一些任意事件,這將是適當的。你的代碼看起來更像後者,所以看起來並不適合你的情況。

+0

這會引發錯誤:'不能將類型'System.EventHandler'隱式轉換爲'System.ComponentModel.PropertyChangedEventHandler''。現在我希望代碼能夠實際處理「自定義事件」以及「內置事件」。所以限制'T'是我其實不想做的事情。 – paul23

+0

@ paul23如果你想解決* any *類型的事件的問題,而不僅僅是一個特定類型的委託,那麼你的問題是一樣的[這個問題](https://stackoverflow.com/questions/12865848/general-purpose-fromevent-method),這並不是你想要的東西,但如果這就是你必須做的,那就是你必須做的。 – Servy

+0

那麼問題是,我有一個'PropertyChanged','PropertyChanging','DataChanged','DataChanging'和基於集合的事件,我都需要「測試」幾種不同類型的對象。 - 代碼重複是否真的是這種「標準」方式? (對於我的技能組合來說,鏈接的答案對於目前來說確實「太難了」,使其不適合作爲測試工具)。 – paul23