2010-04-08 49 views
4

我只是新單元測試和ASP.NET MVC。我一直在試圖用Steve Sanderson的「Pro ASP.NET MVC框架」讓我的頭腦同時進入。在這本書中有這樣一段代碼:Moq中的Verify()有多可靠?

public class AdminController : Controller 
{ 
... 

    [AcceptVerbs(HttpVerbs.Post)] 
    public ActionResult Edit(Product product, HttpPostedFileBase image) 
    { 
     ... 
     productsRepository.SaveProduct(product); 

     TempData["message"] = product.Name + " has been saved."; 
     return RedirectToAction("Index"); 
    } 
} 

那他測試,像這樣:

[Test] 
public void Edit_Action_Saves_Product_To_Repository_And_Redirects_To_Index() 
{ 
    // Arrange 
    AdminController controller = new AdminController(mockRepos.Object); 

    Product newProduct = new Product(); 

    // Act 
    var result = (RedirectToRouteResult)controller.Edit(newProduct, null); 

    // Assert: Saved product to repository and redirected 
    mockRepos.Verify(x => x.SaveProduct(newProduct)); 
    Assert.AreEqual("Index", result.RouteValues["action"]); 
} 

測試通過。

因此,我故意通過添加「productsRepository.DeleteProduct(product);」來破壞代碼。之後的「SaveProduct(產品)」;「如:

  ... 
     productsRepository.SaveProduct(product); 
     productsRepository.DeleteProduct(product); 
      ... 

測試通過(即縱容災難性[催眠+智能感知誘導的錯字:))

可這測試寫入更好?或者有什麼我應該知道的?非常感謝。

回答

7

我想你可能會誤解.Verify()方法的用途。

它驗證給定的方法是否以期望的值被調用。

Steve在說'注意它是如何使用Moqs .Verify()方法確保AdminController確實使用正確的參數調用DeleteProduct()。'

所以在你的情況下,測試通過,因爲它只是驗證呼叫而不是功能。

正如TDD正在書的過程中,加入的過程中,隨後

productsRepository.DeleteProduct(product); 

應首先被添加到測試

// Assert: Saved product to repository, then deleted and redirected 
mockRepos.Verify(x => x.SaveProduct(newProduct)) 
mockRepos.Verify(x => x.DeleteProduct(newProduct)); 
Assert.AreEqual("Index", result.RouteValues["action"]); 

,然後添加到代碼

[AcceptVerbs(HttpVerbs.Post)] 
public ActionResult Edit(Product product, HttpPostedFileBase image) 
{ 

    ... 
productsRepository.SaveProduct(product); 
productsRepository.DeleteProduct(product); 
    ... 
0

這個想法是「編寫最簡單的代碼」。這有助於避免在增量計數器操作中執行諸如從磁盤刪除文件等蠢事。顯然,不刪除文件更簡單。

2

您的代碼故意「損壞」不會中斷測試,因爲您在Verify()SaveProduct()之後完成了測試。我一直髮現Moq的Verify()非常可靠。

一些僞代碼,一個更強大的測試可能是有你的資料庫實現一個接口,並有一個簡單的內存可測試版本

// Arrange 

var repo = SetupTestableRepository() 
var product = CreateProduct(productId) 

// Act 
repo.SaveProduct(product) 

// Assert 
Assert.IsNotNull(repo.Fetch(productId)) 

善良,

4

正如其他人所說,測試通過,因爲你的斷言:

mockRepos.Verify(x => x.SaveProduct(newProduct)); 

已完成。你的代碼做了調用SaveProduct方法。

Mock.Verify()方法無法驗證其他方法不是調用,這是您期望它執行的操作。

如果您擔心會發生奇怪的事情(比如在Save()之後調用Delete()並希望通過測試阻止它),那麼您也必須爲該條件添加Verify() 。例如:

mockRepos.Verify(x => x.DeleteProduct(newProduct), Times.Never()); 
+0

是的。一些模擬框架支持嚴格的模擬,這將驗證模擬上沒有其他方法被調用,但這些方法往往導致脆弱的測試。 – TrueWill 2010-04-09 22:19:50