Asp.Net MVC教程单元测试

时间:2010-04-06 10:26:34

标签: asp.net-mvc unit-testing

我正在研究Steve Sanderson的书Pro ASP.NET MVC Framework,我遇到了两个产生错误的单元测试的问题。

在下面的示例中,它测试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(Release Candidate 2)解决了围绕TryUpdateModel的任何问题,并且网站按预期运行。

相关的错误消息是:

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)

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

1 个答案:

答案 0 :(得分:2)

你必须模拟Controller的HttpContext来编写这样的测试。 MvcContrib库让它变得非常简单。

我更喜欢的另一个选项是将“TryUpdateModel”完成的逻辑提取到自定义的ModelBinder中。然后,您可以与更新模型的逻辑分开测试结帐操作方法的逻辑。 不需要HttpContext。