2012-03-07 100 views
5

假設我有幾個OrderProcessor s,它們中的每一個都有不同的處理順序。
哪些OrderProcessor使用根據Order對象的屬性來完成,並通過工廠方法完成的,像這樣的決定:單元測試工廠方法

public IOrderProcessor CreateOrderProcessor(IOrdersRepository repository, Order order, DiscountPercentages discountPercentages) 
{ 
    if (order.Amount > 5 && order.Unit.Price < 8) 
    { 
     return new DiscountOrderProcessor(repository, order, discountPercentages.FullDiscountPercentage); 
    } 

    if (order.Amount < 5) 
    { 
     // Offer a more modest discount 
     return new DiscountOrderProcessor(repository, order, discountPercentages.ModestDiscountPercentage); 
    } 

    return new OutrageousPriceOrderProcessor(repository, order); 
} 

現在,我的問題是,我想驗證返回OrderProcessor已收到正確的參數(例如 - 正確的折扣百分比)。
但是,這些屬性在OrderProcessor實體上未公開。

你會如何處理這種情況?

唯一的解決辦法我能想出是使OrderProcessor公共的折扣百分比屬性,但它似乎像矯枉過正這樣做只是爲單元測試的目的...

回答

3

解決此問題的一種方法是將要測試的字段更改爲內部而不是私有,然後將項目的內部設置爲對測試項目可見。你可以閱讀這個在這裏:http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.internalsvisibletoattribute.aspx

你會做這樣的事情在你的AssemblyInfo.cs文件:

[assembly:InternalsVisibleTo("Orders.Tests")] 

雖然你可能會說,你的單元測試不一定在乎你的私人領域類。也許最好是將值傳遞給工廠方法,並在接口上調用某種方法(假設Calculate()或類似方法)時爲預期結果編寫單元測試。

或者另一種方法是單元測試具體類型(DiscountOrderProcessor等)並確認其公共方法/屬性的返回值。然後爲工廠方法編寫單元測試,以便正確返回正確類型的接口實現。

這些是我在編寫類似代碼時通常採用的方法,但是有很多不同的方法來解決這樣的問題。我會建議搞清楚你會在單元測試中獲得最大的價值,並根據這個來寫。

1

如果折扣百分比不公開,那麼它不是IOrderProcessor合同的一部分,因此不需要驗證。只需對DiscountOrderProcessor進行一組單元測試,以驗證它是否根據通過構造函數傳入的折扣百分比正確計算折扣。

+1

雖然這是好主意似乎有理由想知道正在使用正確的折扣百分比,否則有人可以修改代碼以使兩個頂部路徑返回'discountPercentages.FullDiscountPercentage',沒有人會知道,一下子人就開始得到充分的折扣,而不是溫和的一個 – 2012-03-07 18:16:10

+0

好,把DiscountOrderProcessor創建一個虛擬方法,並確保它被稱爲根據您廠的邏輯適當的參數。 – PatrickSteele 2012-03-07 18:39:11

+0

我將不得不同意帕特里克。這聽起來像你正在冒險從單元測試到集成測試(這也很重要)。單元測試是針對一個邏輯單元的,每個訂單處理器都應該有自己的單元測試。 – 2013-10-30 21:40:16

0

你有幾個選擇,因爲我看到它。你可以創建專業化DiscountOrderProcessor的:

public class FullDiscountOrderProcessor : DiscountOrderProcessor 
{ 
    public FullDiscountOrderProcessor(IOrdersRepository repository, Order order):base(repository,order,discountPercentages.FullDiscountPercentage) 
    {} 
} 

public class ModestDiscountOrderProcessor : DiscountOrderProcessor 
{ 
    public ModestDiscountOrderProcessor (IOrdersRepository repository, Order order):base(repository,order,discountPercentages.ModestDiscountPercentage) 
    {} 
} 

,並檢查返回正確的類型。

你可以通過工廠創建DiscountOrderProcessor,只需要一定的金額,那麼你可以檢查這是用正確的參數調用。

您可以提供一個虛擬方法來創建DiscountOrderProcessor,並檢查使用正確的參數調用。

我很喜歡個人的第一個選項,但所有這些方法從有同樣的問題,到底你不能檢查實際值,因此有人可以改變你的折扣金額,你不會不知道。即使採用第一種方法,您最終也無法測試應用於FullDiscountOrderProcessor的值。

你需要有某種方式來檢查它留給你的實際值:

你可以把屬性的公共(或內部 - 使用InternalsVisibleTo),這樣你可以詢問他們。

,你可以把返回的對象,並檢查其是否正確應用折扣的一些對象,你傳遞給它。

就我個人而言,我會去製作屬性內部,但它取決於對象如何交互,如果將模擬對象傳遞給折扣訂單處理器並驗證其正確執行操作很簡單,那麼這可能是一個解決方案更好