我的MVC4应用程序中有一个Edit Post操作方法,我正在尝试对此操作进行单元测试。但是,单元测试失败了" NullReferenceException"。以下是单元测试FYR。
[TestMethod]
public void EditAction_Should_Redirect_When_Update_Successful()
{
// Arrange
var mockHttpContext = new Mock<HttpContextBase>();
var mockRequest = new Mock<HttpRequestBase>();
mockHttpContext.Setup(x => x.Request).Returns(mockRequest.Object);
// tell the mock to return "POST" when HttpMethod is called
mockRequest.Setup(x => x.HttpMethod).Returns("POST");
mockRequest.SetupGet(req => req.Form).Returns(new FormCollection());
var controller = GetTheController();
var id = 1;
// assign the fake context
var context = new ControllerContext(mockHttpContext.Object,
new RouteData(),
controller);
controller.ControllerContext = context;
var formValues = new MyModel() {
Id = 1,
ActivityDescription = "This is another description",
CreatedDate", Convert.ToDateTime("31-12-2014"),
UserId = 1,
IsCompleted = false
};
// Act
var result = controller.Edit(id, formValues) as RedirectToRouteResult;
// Assert
Assert.AreEqual("List", result.RouteValues["Action"]);
Assert.AreEqual(id, result.RouteValues["id"]);
}
编辑操作方法如下 -
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(MyModel item)
{
var viewResult = ValidateItem(item);
if (viewResult != null)
return viewResult;
//Unit test is failing at this step.
TryUpdateModel(item);
if (ModelState.IsValid)
{
_itemsRepository.Edit(item);
return RedirectToAction("Index");
}
else return View(item);
}
以下是用于参考的堆栈跟踪 -
测试结果:失败 测试时间:0:00:00.3306816
结果讯息:
Test method MvcToDoListItemsDemo.Tests.TodoControllerTest.EditAction_Should_Redirect_When_Update_Successful threw exception:
System.NullReferenceException: Object reference not set to an instance of an object.
Result StackTrace:
at Microsoft.Web.Infrastructure.DynamicValidationHelper.DynamicValidationShim.IsValidationEnabled(HttpContext context)
at Microsoft.Web.Infrastructure.DynamicValidationHelper.ValidationUtility.IsValidationEnabled(HttpContext context)
at Microsoft.Web.Infrastructure.DynamicValidationHelper.ValidationUtility.GetUnvalidatedCollections(HttpContext context, Func`1& formGetter, Func`1& queryStringGetter)
at System.Web.Helpers.Validation.Unvalidated(HttpRequest request)
at System.Web.Mvc.FormValueProviderFactory.<.ctor>b__0(ControllerContext cc)
at System.Web.Mvc.FormValueProviderFactory.GetValueProvider(ControllerContext controllerContext)
at System.Web.Mvc.ValueProviderFactoryCollection.<>c__DisplayClassc.<GetValueProvider>b__7(ValueProviderFactory factory)
at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
at System.Web.Mvc.ValueProviderFactoryCollection.GetValueProvider(ControllerContext controllerContext)
at System.Web.Mvc.ControllerBase.get_ValueProvider()
at System.Web.Mvc.Controller.TryUpdateModel[TModel](TModel model)
有人可以告诉我这里是否做错了什么?
此致 拉姆
答案 0 :(得分:1)
TryUpdateModel(item)
从控制器的默认item
获取ValueProvider
的更新值,通常是System.Web.Mvc.FormValueProvider
,后者从当前的POST请求正文中解析它们。在单元测试中,您可以将模型包装在DictionaryValueProvider<object>
中并按原样返回,如下所示:
var controller = GetTheController();
var requestModel = new MyModel()
{
/* .. values .. */
};
controller.ValueProvider = new DictionaryValueProvider<object>(
new Dictionary<string, object>() { { "MyModel", requestModel } }, null);
var result = controller.Edit(id) as RedirectToRouteResult;