2014-02-25 101 views
0

所以我對測試很新,我從來沒有做過很多,所以我可能缺乏一些基礎知識。如何用Moq位置/過程進行單元測試

問題1: 我正在使用ASP MVC4並希望使用Moq與我的單元測試用例。閱讀後有很多例子,我看到我有一個接口。這應該去哪裏?在控制器文件夾中,測試項目?

問題2 如果我測試我控制器的方法,它有我怎麼會起訂量是

public ActionResult Index() 
{ 
var model = new myModel(); 
var pList = new List<myModel.pType>(); 
var sList = new List<myModel.sType>(); 
var results = Class1.FetchPData(); // how would I mock this 
var result1 = Class1.FetchSData(); // how would I mock this 

for (int i = 0; i < results.Count(); i++) 
{ 
    ... do stuff 
} 


for (int j = 0; j < result1.Count(); j++) 
{ 
    ..do stuff 
} 

    return View("Index", model); 
} 

請問我要創建另一個方法,其中包含相同的分貝多個呼叫邏輯,但是我必須傳入「模擬對象」作爲方法的參數,並將其作爲我的界面中的可實現方法?或者重新實施我的方法?

回答

2

閱讀後有很多的例子,我看到我假設有 有一個接口。這應該去哪裏?在控制器 文件夾中,測試項目?

沒有規則在哪裏保留接口,但通常你保持它們密切使用它們的代碼。通常我有單獨的程序集中的域類和服務,其中定義了存儲庫接口。然後,我通過具有存儲庫接口實現的數據訪問程序集來引用此程序集。最後一步 - 我從web應用程序中引用這兩個程序集。

如果我測試我控制器的方法,它有多次調用 分貝我怎麼會起訂量是

記住,良好的單元測試應該是快速的,孤立的,重複的,自我驗證並及時(FIRST)。在控制器中進行數據庫調用不允許您快速運行測試(與內存代碼相比,數據庫調用非常緩慢),以獨立地測試控制器並使測試始終可重複。此外,您的控制器只是做很多事情(即違反SRP原則) - 它獲取用戶輸入,進行數據庫查詢併爲查看準備模型。

因此,以分離的責任,使你的控制器可測試,你應該 提取數據訪問相關的代碼到單獨的類(通常這樣的類被稱爲)。並創建了一個抽象,將控制器和存儲庫之間的指定API:

public interface IYourRepository 
{ 
    IEnumerable<pType> FetchPData(); 
    IEnumerable<sType> FetchSData(); 
} 

然後讓你的控制器依賴於這種抽象(逆相關性),並注入存儲庫控制器(可以使用Ninject,統一或其他依賴注入框架) :

IYourRepository _repository; 

public YourController(IYourRepository repository) 
{ 
    _repository = repository; 
} 

public ActionResult Index() 
{ 
    var model = new myModel(); 

    foreach (var p in _repository.FetchPData()) 
     // do stuff 

    foreach (var s in _repository.FetchSData()) 
     // do stuff 


    return View("Index", model); 
} 

,讓您可以輕鬆地嘲笑庫,並提供嘲笑對象控制器:

var repositoryMock = new Mock<IYourRepository>(); 
repositoryMock.Setup(r => r.FetchPData()).Returns(pList); 
repositoryMock.Setup(r => r.FetchSData()).Returns(sList); 

var controller = new YourController(repositoryMock.Object); 
var result = controller.Index(); 

// Assertions 
+0

好吧,我明白知道。所以在將來,我應該用一種也可以輕鬆模擬的方式編寫我的方法 –

+0

我應該提到'FetchPData'和'FetchSData'實際上是從另一個類調用的靜態方法。 –

+0

@JackThor即使在你編輯問題後,答案也是一樣的 - 使它們非靜態並向控制器注入另一個類實例 –