2015-11-12 78 views
0

我是一個絕對的初學者,測試和.net,我需要儘快測試這種方法的學校項目。有人可以告訴我如何測試這種方法

這是代碼:

// GET: Books/Archive 
public async Task<ActionResult> Archive() 
{ 
    var usersBooks = await _bookManager.GetArchiveBooks(Guid.Parse(HttpContext.User.Identity.GetUserId())); 

    var result = usersBooks.Select(ConvertArchiveBookToViewModel).ToList(); 

    return View(new ArchiveViewModel 
     { 
      Books = result 
     }); 
} 

任何答案將是真正的幫助,並感謝您:)

+2

From [Help](http://stackoverflow.com/help/on-topic):提問作業幫助的問題必須包括您迄今爲止解決問題所做的工作摘要,以及你正在解決它的困難。 –

+0

你當然可以看看像Autofac這樣的IoC,並使用Moq框架來模擬_bookManager類。 –

回答

3

第一件事的第一......你需要模擬_bookManager作爲此方法的依賴。

_bookManager從哪裏來?據推測這是一個班級財產。所以它應該提供一些方法來使用模擬。你應該可能使用構造函數注入,但如果你不熟悉ASP.NET MVC中的依賴關係,那麼它現在可能會過於複雜。注射財產也應該如此。事情是這樣的:

public class MyController 
{ 
    private SomeType _bookManager; 
    public SomeType BookManager 
    { 
     get { return _bookManager; } 
     set { _bookManager = value; } 
    } 

    public async Task<ActionResult> Archive() 
    { 
     // your method 
    } 
} 

想必也是有代碼在類在使用它之前,否則初始化_bookManager別處。你將要修改該邏輯,以便它不覆蓋任何提供的模擬。一種對我來說經常效果好的模式是使用屬性本身,即使是內部的屬性,也可以在屬性中進行惰性初始化。事情是這樣的:

public class MyController 
{ 
    private SomeType _bookManager; 
    public SomeType BookManager 
    { 
     get 
     { 
      if (_bookManager == null) 
       _bookManager = new SomeType(); 
      return _bookManager; 
     } 
     set { _bookManager = value; } 
    } 

    public async Task<ActionResult> Archive() 
    { 
     // IMPORTANT: Use "BookManager" instead of "_bookManager" 
    } 
} 

這裏的想法是,如果您爲BookManager提供一個模擬(或任何依賴實現),那麼代碼將使用它。否則,它會使用你正在使用的任何東西。

既然您的課程設置爲允許使用模擬,您需要創建一個模擬。有許多嘲笑圖書館可用。我個人使用RhinoMocks。

模擬的目的是提供預期的,定義的行爲。這是因爲...

您正在測試Archive()。您是測試BookManager.GetArchiveBooks()

使用您選擇的嘲弄庫,在您的測試,你將設立的SomeType實例(或任何你喜歡的類型叫,很明顯)返回從定義和預期的結果GetArchiveBooks()。根據這個結果,你可以預測你正在測試的方法的結果並驗證它產生的結果。

從廣義上說,你的測試將是這個樣子:

// arrange 
var bookManager = MockRepository.GenerateMock<SomeType>(); 
// TODO: configure the object to return a known result from GetArchiveBooks() 
var controller = new MyController(); 
controller.BookManager = bookManager; 

// act 
var result = await controller.Archive(); 

// assert 
// TODO: inspect the result to ensure it contains what you expect 

對於您所選擇的嘲弄庫,看看設立了方法的「存根」一些例子被稱爲(在這種情況下爲GetArchiveBooks())。

爲了檢查結果,首先你要在調試器中逐步完成這個測試,看看result實際上有什麼。一個視圖結果有很多屬性,我不知道它們在我頭頂。但是如果你在調試器中檢查它,你應該能夠在其中一個屬性中找到你的模型,以及如果你願意的話你可能會驗證的潛在的其他事情。 (取決於你想在這個測試中聲明多少事情。)

此處的目標是確保返回的模型是,正好是您期望它基於模擬依賴關係的已知行爲。如果是,則該方法通過測試。


編輯:我只注意到在方法的第二依賴性:

HttpContext.User.Identity.GetUserId() 

現代ASP.NET MVC的實現可以提供一些有益的方式來嘲笑HttpContext爲好,雖然我不熟悉我的頭頂。最糟糕的情況是,你只是暴露另一個注射屬性來嘲笑它。事情是這樣的:

private string _userID; 
public string UserID 
{ 
    get 
    { 
     if (string.IsNullOrWhiteSpace(_userID)) 
      _userID = HttpContext.User.Identity.GetUserId(); 
     return _userID; 
    } 
    set { _userID = value; } 
} 

然後在動作方法,你能使用該財產而不是直接調用HttpContext。在你的測試中,作爲「安排」步驟的一部分,你會提供一個模擬字符串。這是很簡單的:

controller.UserID = "testUser"; 

正如你可以在這一點看,可測試性所有關於依賴管理。每個單獨的可測試代碼應該與任何和所有的依賴關係隔離,無論它們有多小。 (如從HttpContext獲取用戶標識。)"Invert" those dependencies允許代碼提供信息,而不是讓您的可測試代碼負責獲取信息。

+0

非常感謝你的回覆真的有用:) –

相關問題