2010-04-06 75 views
1

我正在通过史蒂夫桑德森的书Pro ASP.NET MVC框架和我有两个单元测试产生错误的问题。Asp.Net MVC教程单元测试

在它下面的示例测试CheckOut ViewResult

[AcceptVerbs(HttpVerbs.Post)] 
public ViewResult CheckOut(Cart cart, FormCollection form) 
{ 
     // Empty carts can't be checked out 
     if (cart.Lines.Count == 0) 
     { 
      ModelState.AddModelError("Cart", "Sorry, your cart is empty!"); 
      return View(); 
     } 

     // Invoke model binding manually 
     if (TryUpdateModel(cart.ShippingDetails, form.ToValueProvider())) 
     { 
      orderSubmitter.SubmitOrder(cart); 
      cart.Clear(); 
      return View("Completed"); 
     } 
     else // Something was invalid 
      return View(); 
} 

用下面的单元测试

[Test] 
public void Submitting_Empty_Shipping_Details_Displays_Default_View_With_Error() 
{ 
    // Arrange 
    CartController controller = new CartController(null, null); 
    Cart cart = new Cart(); 
    cart.AddItem(new Product(), 1); 
    // Act 
    var result = controller.CheckOut(cart, new FormCollection { 
     { "Name", "" }            
    }); 
    // Assert 
    Assert.IsEmpty(result.ViewName); 
    Assert.IsFalse(result.ViewData.ModelState.IsValid); 
} 

我已经升级到ASP.NET MVC 2(发布候选解决周边TryUpdateModel任何问题2)和网站按预期运行。

相关的错误信息是:

Tests.CartControllerTests.Submitting_Empty_Shipping_Details_Displays_Default_View_With_Error: 
System.ArgumentNullException : Value cannot be null. 
Parameter name: controllerContext 

和更详细的

at System.Web.Mvc.ModelValidator..ctor(ModelMetadata metadata, ControllerContext controllerContext) 
at System.Web.Mvc.DefaultModelBinder.OnModelUpdated(ControllerContext controllerContext, ModelBindingContext bindingContext) 
at System.Web.Mvc.DefaultModelBinder.BindComplexModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
at System.Web.Mvc.Controller.TryUpdateModel[TModel](TModel model, String prefix, String[] includeProperties, String[] excludeProperties, IValueProvider valueProvider) 
at System.Web.Mvc.Controller.TryUpdateModel[TModel](TModel model, IValueProvider valueProvider) 
at WebUI.Controllers.CartController.CheckOut(Cart cart, FormCollection form) 

有没有人遇到类似的问题或得到测试通过?

回答

2

你必须模拟控制器的HttpContext来编写这样的测试。 MvcContrib库使它非常简单。

我更喜欢的另一种选择是将“TryUpdateModel”完成的逻辑提取到自定义的ModelBinder中。然后,您可以独立于更新模型的逻辑来测试检出操作方法的逻辑。 不需要HttpContext。

+0

@serbrech在这种情况下,我使用Moq,因此我添加了以下内容,现在可以使用。谢谢。 var controllerContext = new Moq.Mock (); controller.ControllerContext = controllerContext.Object; – 2010-04-06 11:31:01

+0

,但是你可能会有更多的东西在后面嘲笑HttpContext,并且它很快就会变得非常棘手,嘲笑它。 MvcContrib有一些为你初始化的testHelpers;)。 – 2010-04-06 11:35:40