【问题标题】:How do I Fake UpdateModel for ASP.Net MVC?我如何伪造 ASP.Net MVC 的 UpdateModel?
【发布时间】:2010-12-14 20:45:20
【问题描述】:

我正在尝试对使用 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 项目中的测试助手来实现相同目标的示例。

【问题讨论】:

  • 鉴于其复杂性,您确定不想只使用强类型的 ViewData 对象吗?
  • 在 get 上传递给视图的模型是强类型的。我不知道您可以将强类型模型发布到操作中。
  • ViewData["message"] 与错误视图一起使用,这是一种通用共享视图,用于在出现问题时发送消息。

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


【解决方案1】:

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

您只需将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
}

HTH,
查尔斯

【讨论】:

  • 我仍然需要模拟 HttpContext 对 User.Identity 调用所做的事情,但你就是钱。
  • True true... 没有注意那个 User.Identity 调用 :-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-10-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多