如何伪造ASP.Net MVC的UpdateModel?

时间:2009-11-10 00:34:36

标签: c# .net asp.net-mvc unit-testing rhino-mocks

我正在尝试对使用UpdateModel的控制器操作进行单元测试,但我没有正确地模拟HttpContext。我一直得到以下例外:

  

System.InvalidOperationException:上一个方法'HttpRequestBase.get_Form();'需要返回值或抛出异常。

为了模拟HttpContext,我使用的东西类似于scott posted for Rhino mocks

我添加了一个方法,我认为会模仿'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);
}

以下是单元测试:

[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);

}

正在测试的控制器操作:

[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 });
}

我会接受任何正确修改我的SetupRequestForm,单元测试的答案,或者发布一个关于如何在MVCContrib项目中使用测试助手实现相同目标的示例。

1 个答案:

答案 0 :(得分:3)

您没有使用已传入操作方法的FormCollection。您通常传入FormCollection的原因是通过打破对HttpConext的UpdateModel依赖来帮助进行测试。

您需要做的就是将UpdateModel行更改为:

UpdateModel(style, collection.ToValueProvider());

完成后,您可以忘记设置模拟HttpContext。例如。您的测试现在可以如下所示:

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

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

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

    //Blah
}

HTHS,
查尔斯