如何为ASP.Net MVC伪造UpdateModel?

I am trying to unit test a controller action that uses UpdateModel but I am not correctly mocking the HttpContext. I keep getting the following exception:

System.InvalidOperationException: Previous method 'HttpRequestBase.get_Form();' requires a return value or an exception to throw.

To mock the HttpContext I am using some thing similar to what scott posted for Rhino mocks.

I added one method for what I thought would mock the 'HttpRequestBase.get_Form();'

public static void SetupRequestForm(this HttpRequestBase request, NameValueCollection nameValueCollection)
{
    if (nameValueCollection == null)
        throw new ArgumentNullException("nameValueCollection");
    SetupResult.For(request.PathInfo).Return(string.Empty);
    SetupResult.For(request.Form).Return(nameValueCollection);
}

Here is the unit test:

[Test]
public void Edit_GivenFormsCollection_CanPersistStyleChanges()
{
    //in memory db setup omitted ...

    var nameValueCollection = new NameValueCollection();
    InitFormCollectionWithSomeChanges(nameValueCollection, style);
    var httpContext = _mock.FakeHttpContext();
    _mock.SetFakeControllerContext(controller, httpContext);
    httpContext.Request.SetupRequestForm(nameValueCollection);

    controller.Edit(1, new FormCollection(nameValueCollection));

    var result = (ViewResult)controller.Edit(1);

    Assert.IsNotNull(result.ViewData);
    style = Style.GetStyle(1);
    AsserThatModelCorrectlyPersisted(style);

}

The controller action under test:

[Authorize]
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(int id, FormCollection collection)
{
    var campaign = Campaign.GetCampaign(id);

    if (campaign == null)
        return View("Error", ViewData["message"] = "Oops, could not find your requested campaign.");
    if (!campaign.CanEdit(User.Identity.Name))
        return View("Error", ViewData["message"] = "You are not authorized to edit this campaign style.");

    var style = campaign.GetStyle();
    //my problem child for tests.
    UpdateModel(style);

    if (!style.IsValid)
    {
        ModelState.AddModelErrors(style.GetRuleViolations());
        return View("Edit", style);
    }

    style.Save(User.Identity.Name);
    return RedirectToAction("Index", "Campaign", new { id });
}

I will accept any answer that correctly modifies my SetupRequestForm, unit test, or posts an example on how to use the Test helpers in the MVCContrib project to achieve the same goal.

#0

You're not using the FormCollection that you've passed in to you action method. The reason you usually pass in a FormCollection is to aid in testing by breaking the UpdateModel dependency on the HttpConext.

All you need to do is change your UpdateModel line to:

UpdateModel(style, collection.ToValueProvider());

Once you've done that you can forget about setting up your mock HttpContext. E.g. your test could now read like:

[Test]
public void Edit_GivenFormsCollection_CanPersistStyleChanges()
{
    //Blah

    var nameValueCollection = new NameValueCollection();
    InitFormCollectionWithSomeChanges(nameValueCollection, style);
    //Removed stuff

    controller.Edit(1, new FormCollection(nameValueCollection));

    //Blah
}

HTHs,
Charles

推荐文章

链接到Joomla 1.5中自定义组件的内部页

链接到Joomla 1.5中自定义组件的内部页

推荐文章

WPF组合框不响应鼠标

WPF组合框不响应鼠标

推荐文章

Zend Framework:向Zend_Amf添加类是否会实例化它?

Zend Framework:向Zend_Amf添加类是否会实例化它?

推荐文章

SHGetPathFromIDList()(和类似的)是否在其参数中放置了终止的0?

SHGetPathFromIDList()(和类似的)是否在其参数中放置了终止的0?

推荐文章

替换?请求重写规则

替换?请求重写规则

推荐文章

从HttpServletRequest获取原始请求字符串

从HttpServletRequest获取原始请求字符串

推荐文章

如何在ASP.NET MVC中长时间轮询AJAX请求?

如何在ASP.NET MVC中长时间轮询AJAX请求?

推荐文章

帮助gcc不警告不使用字符串文本格式字符串

帮助gcc不警告不使用字符串文本格式字符串

推荐文章

如何遍历Perl数组引用?

如何遍历Perl数组引用?

推荐文章

塔架应用程序的机头测试,模型为初始模型?

塔架应用程序的机头测试,模型为初始模型?

推荐文章

xslt-提取叶节点

xslt-提取叶节点

推荐文章

iPhone Web开发图像缩放

iPhone Web开发图像缩放

推荐文章

wshshell.run(InstallPath,0,true)不等待完成安装并继续脚本

wshshell.run(InstallPath,0,true)不等待完成安装并继续脚本

推荐文章

使用时间间隔的最佳方法?

使用时间间隔的最佳方法?

推荐文章

在差异输出中显示行内的差异

在差异输出中显示行内的差异

推荐文章

查询多个表并且只返回一个数组?

查询多个表并且只返回一个数组?