簡體   English   中英

如何為存儲庫設置Moq

[英]How to setup Moq for repository

我有方法

public IEnumerable<string> LoadCountries()
{
     try
     {
         return GetAll().GetCountries();
     }
     catch (Exception)
     {
          return null;
     }
 }

GetAll()方法從SQL Server加載數據,但是在測試中不需要它,所以我在IEnumerable客戶上更改了數據庫。 我想測試一下

Mock<ICustomersRepository> mock = new Mock<ICustomersRepository>();
mock.Setup(m => m.GetAll()).Returns(customers.AsQueryable()); //change data
IEnumerable<string> countries = mock.Object.LoadCountries();
Assert.AreEqual(countries.Count(), 6); //expect 6 countries

但是在這個測試國家/地區,Count()== 0; 我可以修改模擬設置並添加

mock.Setup(m => m.LoadCountries()).Returns(customers.AsQueryable().GetCountries());

但是我不想這樣做,因為我要測試的其他功能要大得多。 有誰知道如何設置GetAll()函數以返回我的測試數組,即使GetAll()在測試類內部實現也是如此? 我只是嘗試設置

mock.CallBase = true;
mock.Setup(m => m.LoadCountries()).CallBase();

但我只是看到異常

System.NotImplementedException:這是一個DynamicProxy2錯誤:攔截器嘗試為方法“繼續”
沒有目標的'System.Collections.Generic.IEnumerable`1 [System.String] LoadCountries()'。 當調用沒有目標的方法時,沒有實現要“進行”,並且攔截器有責任模仿實現(設置返回值,輸出參數等)。

您正在創建實現ICustomersRepository接口的動態代理類。 然后,您將行使此生成的代理:

Mock<ICustomersRepository> mock = new Mock<ICustomersRepository>();
IEnumerable<string> countries = mock.Object.LoadCountries();

那不是一個好主意。 您通過該測試驗證什么? 代理生成? 代理不會被您的真實代碼使用。 您應該使用模擬來提供模擬的依賴關系,以測試應用程序使用的真實類。

其實我不會測試LoadCountries()調用GetAll()內部。 因為這是實現的詳細信息,而不是客戶存儲庫的業務要求。 我會編寫一些驗收/集成測試,以驗證給定的客戶是否返回了正確的國家。

更新:因此,您的GetCountries()過濾器是一個擴展,因此您不需要在其測試中涉及存儲庫。 多數民眾贊成在一個簡單的靜態類,可以單獨進行測試。 但是,您的測試無需與數據庫交互也不會很有價值,因為您的擴展程序會將查詢組成對數據源的查詢,該查詢將由查詢提供程序進行翻譯。 我舉一個例子。 如果您有本地方法調用(或查詢提供程序無法轉換的方法):

public static class Extensions
{
    public static IQueryable<string> GetCountries(this IQueryable<Customer> q) 
    {
        return q.GroupBy(c => c.Country).Select(x => LocalMethod(x.Key)); 
    }

    private static string LocalMethod(string country)
    {
        return country.ToUpper();
    }
}

然后,當您使用內存中的對象時,以下單元測試將通過:

List<Customer> customers = new List<Customer> {
    new Customer { Country = "USA" },
    new Customer { Country = "Spain" }
};

var countries = Extensions.GetCountries(customers.AsQueryable());
Assert.AreEqual(countries.Count(), 2);

但是,當您運行使用Entity Framework查詢SQL數據庫的應用程序時,EF將無法將此過濾器轉換為SQL。

但是,如果您要測試存儲庫,而LoadCountries在存儲庫層中,則不應模擬存儲庫。

您不能在沒有指定某些Return()的情況下對模擬對象使用存儲庫方法;)

如果模擬回購是因為您不想連接到testa dn的數據庫,則想使用例如以下方式檢索模擬數據:

List<Country> myList = //Fill your list with countries
repo.Setup(x => x.LoadCountries).Return(myList);

然后,使用其他部分來使用此模擬數據。

但是正如我所說,如果您要測試存儲庫,則不應對其進行模擬。

當您嘗試例如對業務部分進行測試時,您可以對存儲庫進行模擬,然后需要從數據庫中獲取一些虛假數據,然后對存儲庫進行模擬,並獲得虛假數據;)

如果是這種情況,則:

Mock<ICustomersRepository> mock = new Mock<ICustomersRepository>();
mock.Setup(x => x.LoadCountries).Return(myList);

然后,例如,如果您從業務層在構造函數中詢問ICustomersRepository,則可以在業務層創建實例並傳遞此模擬存儲庫。

MyService service = new MyService(mock.Object);
service.LoadAll();

如果此LoadAll()使用LoadCountries,則當此LoadAll調用LoadCountries時,它將獲得您所在國家的模擬數據!

我希望這有幫助!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM