我一直在研究Scott Guthrie关于ASP.NET MVC Beta 1的优秀帖子.在其中,他展示了对UpdateModel方法所做的改进以及它们如何改进单元测试.我已经重新创建了一个类似的项目,但是当我运行包含对UpdateModel的调用的UnitTest时,我会收到一个名为controllerContext参数的ArgumentNullException.
这是相关的位,从我的模型开始:
public class Country { public Int32 ID { get; set; } public String Name { get; set; } public String Iso3166 { get; set; } }
控制器动作:
[AcceptVerbs(HttpVerbs.Post)] public ActionResult Edit(Int32 id, FormCollection form) { using ( ModelBindingDataContext db = new ModelBindingDataContext() ) { Country country = db.Countries.Where(c => c.CountryID == id).SingleOrDefault(); try { UpdateModel(country, form); db.SubmitChanges(); return RedirectToAction("Index"); } catch { return View(country); } } }
最后我的单元测试失败了:
[TestMethod] public void Edit() { CountryController controller = new CountryController(); FormCollection form = new FormCollection(); form.Add("Name", "Canada"); form.Add("Iso3166", "CA"); var result = controller.Edit(2 /*Canada*/, form) as RedirectToRouteResult; Assert.IsNotNull(result, "Expected to be redirected on successful POST."); Assert.AreEqual("Show", result.RouteName, "Expected to redirect to the View action."); }
ArgumentNullException
通过调用抛出UpdateModel
消息"值不能为空.参数名称:controllerContext".我假设某个地方UpdateModel
需要System.Web.Mvc.ControllerContext
在执行测试期间不存在的地方.
我也假设我在某处做错了,只需指向正确的方向.
请帮忙!
我不认为可以这样做,因为UpdateModel使用的TryUpdateModel引用了ControllerContext,当从单元测试调用时,它是null.我使用RhinoMocks来模拟或存储控制器所需的各种组件.
var routeData = new RouteData(); var httpContext = MockRepository.GenerateStub(); FormCollection formParameters = new FormCollection(); EventController controller = new EventController(); ControllerContext controllerContext = MockRepository.GenerateStub ( httpContext, routeData, controller ); controller.ControllerContext = controllerContext; ViewResult result = controller.Create( formParameters ) as ViewResult; Assert.AreEqual( "Event", result.Values["controller"] ); Assert.AreEqual( "Show", result.Values["action"] ); Assert.AreEqual( 0, result.Values["id"] );
以下是www.codeplex.com/aspnet上Controller.cs源代码中的相关位:
protected internal bool TryUpdateModel( ... ) where TModel : class { .... ModelBindingContext bindingContext = new ModelBindingContext( ControllerContext, valueProvider, typeof(TModel), prefix, () => model, ModelState, propertyFilter ); ... }