2015-08-28 43 views
1

我在寫一些單元測試與犀牛嘲笑爲C#編寫的WPF應用程序使用統一的依賴注入和使用MVVM achitechture工作存根非虛方法。我對Rhino Mocks的單元測試並不是很有經驗,所以我不確定最佳實踐。犀牛製品 - 期待/來自外部的依賴

在視圖模型,我將會寫作單元測試,有一個依賴注入的數據訪問類,我們把它叫做數據訪問,這是從我不控制外部組件。只有一個實例註冊到Unity容器,因爲DataAccess有一個緩存,並且希望通過Unity容器在整個應用程序中共享該實例以提高性能。現在我需要在單元測試中模擬DataAccess,因爲我無法控制數據庫中的數據。我想存根或期望Retrieve方法返回一個特定的值,但DataAccess不實現一個接口,並且我需要的存根方法不是虛擬的。從我在線閱讀的內容可以看出,Rhino Mocks無法重寫非虛擬方法,唯一的選擇是使用要覆蓋的方法來模擬接口。這些選項都不適用於這種情況,因爲我不擁有DataAccess代碼。我聽說TypeMock有能力重寫非虛擬方法,但說服我的公司改用付費嘲笑庫可能不會發生,所以我堅持使用Rhino Mocks。那麼有沒有辦法嘲笑這個類,並用Rhino Mocks重寫這個方法?

public class DataAccess //in an external assembly 
{ 
    public TEntity Retrieve(TKey key); 
} 

public class ViewModel //in the client project 
{ 
    [Dependency] 
    public DataAccess DataAccess { get; set; } 
} 

我想出了一個可能的解決方案,但它不使用模擬考試,我想,因爲有很多地方,我們有這樣的情況下使用模擬考試。我的想法是創建數據訪問包裝類(假的),有除所有的重要的方法相同的方法和屬性數據訪問/屬性標記爲虛擬的,我把這個類在我的測試項目。然後在單元測試初始化​​程序中,我將註冊一個從DataAccess到Unity容器中的包裝類的類型映射,以便在我的單元測試中實例化的VM將獲得包裝類的實例。除了創建一堆包裝類之外,您是否還看到過在這個方向上有什麼缺點?

public class DataAccessFake : DataAccess //in the test project 
{ 
    public new virtual TEntity Retrieve(TKey key) //hides the DataAccess Retrieve with a virtual one 
    { 
     return base.Retrieve(key); 
    } 
} 
+0

這是否實際工作?依賴於DataAccess的對象仍然會調用DataAccess.Retrieve而不是DataAccessFake.Retrieve,這是兩種完全不同的方法。 –

+0

'new'關鍵字指示該方法隱藏其繼承的成員。所以是的,它應該叫做假方法。 – StarChar

+0

你測試過了嗎? –

回答

0

下面是一些代碼,我已經測試表明該建議的方法是行不通的:

class Program 
{ 
    static void Main(string[] args) 
    { 
     ViewModel vm = new ViewModel() 
     { 
      DataAccess = new DataAccessFake() 
     }; 

     string result = vm.Test("test"); //this returns "test_original" 
    } 
} 

public class ViewModel 
{ 
    public DataAccess DataAccess { get; set; } 

    public string Test(string key) 
    { 
     return DataAccess.Retrieve(key); 
    } 
} 

public class DataAccess 
{ 
    public string Retrieve(string key) 
    { 
     return key + "_original"; 
    } 
} 

public class DataAccessFake : DataAccess 
{ 
    public new virtual string Retrieve(string key) 
    { 
     return key + "_fake"; 
    } 
} 

如果你運行這段代碼,測試方法的輸出將是「test_original」這顯示DataAccessFake.Retrieve方法從未被調用過。您也可以在這種方法中放置一個斷點來驗證。

由於視圖模型依賴於數據訪問,它總是會調用DataAccess.Retrieve比DataAccessFake.Retrieve一個完全不同的方法。

當然,該行爲將是非常不同的,如果DataAccessFake.Retrieve一直DataAccess.Retrieve的覆蓋方法。

+0

啊,我明白了。我只測試隱藏的方法是否可以被調用,如果它被聲明爲DataAccessFake。如果它被聲明爲DataAccess但設置爲DataAccessFake的一個實例,它不會調用僞方法。所以我想我的想法不起作用,爲了做到這一點,我不得不用DataAccessFake取代對DataAccess的依賴,這不是一個很好的解決方案。不過謝謝。 – StarChar