2009-09-10 20 views
0

我單元測試一些代碼,與一個存儲庫interactes,其採用表達式(Expression<Func<Entity, bool>>)來過濾結果,像這樣:使用表達式進行單元測試?

int orderId = 10; 

_respository.GetFiltered(order => order.Id == orderId); 

我有一個問題單元測試,更具體地設置預期表達式將匹配。在一個單元測試我想這樣做:

_mockRespository.Setup(r => r.GetFiltered(order => order.Id == 10)).Returns(new Order[0]).AtMostOnce(); 

我找到了一個解決方案,建議在做每個表達.ToString()和compairing的是,然而,當你引用一個變量,如訂單ID,表達的是完全不同的!

人們在做什麼來測試?

感謝,

大衛

+0

不知道我明白...而不是將表達式傳遞給安裝方法。如果將其緩存在本地變量中並將其傳遞給設置方法會怎麼樣。 – Gishu 2009-09-10 12:36:54

+0

如果你這樣做,那麼同樣的問題仍然存在!我如何比較兩個表達式是相同的? – 2009-09-13 10:09:38

回答

0

我會說這是一部分的你真的想驗證與單元測試,這可以歸結爲你的單元測試的理念是什麼的問題。

我們所做的是我們不必驗證從類型A(測試下)傳遞的linq to entities表達式參數在調用存儲庫協作者(不在測試中)的GetFoo()時使用特定的表達式樹。對於單元測試,我們滿足於驗證GetFoo()方法是否正確調用了正確的簽名。

在你的情況下,它看起來像你正在使用MOQ(?),在這種情況下,將成爲這樣的事情(注意語法亂七八糟的)

_mockRespository.Setup(r => r.GetFiltered(It.IsAny<Expression<Func<Entity, bool>>>())).Returns(new Order[0]).AtMostOnce(); 

對我們來說,這是有道理的,因爲一)嘲笑方法參數表達式樹比較驗證確實是一種痛苦,b)即使我們可以驗證該參數,B實際上將如何解釋參數值的不同組合也會發生變化(如同合約A-> B的語義),如果是這種情況,會使測試變得脆弱。

我們使用自動化故事測試來測試生產A和生產B之間的交互。我們認爲這是測試這些場景的更好方法,因爲它們通常類似於'根據表達式X過濾存儲器A中的所有A並給我所有匹配的對象「。對我們來說,這是有道理的,因爲集成測試(通常有一兩個快樂案例足夠)。

如果這還不夠,我會閱讀a)如何創建自定義Moq匹配器,儘管我不能肯定地說有一個簡單的解決方案(可能很好)或者b)設置期望回調,以便您可以捕獲參數並在測試後對其進行檢查。類似這樣的:

Expression<Func<Entity, bool>> actualExpression = null; 
    _mockRespository.Setup(r => r.GetFiltered(It.IsAny<Expression<Func<Entity, bool>>>())).Returns(new Order[0]).AtMostOnce().Callback((Expression<Func<Entity, bool>> expr => { actualExpression = expr}); 

    // exercise production code 

    Assert.IsTrue(actualExpression ...... someithing clever here); 

注意:以上所有代碼都是在堆棧溢出編輯器中編寫的。不要讓我負責,如果它不編譯,Moq文檔覆蓋此