【问题标题】:How to mock Request.IsAjaxRequest() to true using FakeItEasy?如何使用 FakeItEasy 将 Request.IsAjaxRequest() 模拟为 true?
【发布时间】:2015-10-16 05:31:43
【问题描述】:

以下是我要编写单元测试的代码sn-p:

[HttpGet]
public ActionResult Edit(string id)
{
    if (Request.IsAjaxRequest())
    {
        EditModel model = new EditModel();    
        .....
    }
    return View();
}

我想为此操作编写单元测试,我可以将 Request.IsAjaxRequest() 的结果伪造为 true,以便我可以为操作的其余代码编写测试。

我已经尝试过,但它不起作用。 _request.Headers 始终为空,Request.IsAjaxRequest() 始终返回 false:

[Fact]
public void Get_Edit_AjaxRequest_ExpectedActionCalled()
{
    HttpRequestBase _request = A.Fake<HttpRequestBase>();
    _request.Headers.Add("X-Requested-With", "XMLHttpRequest");
    _controller.ControllerContext = A.Fake<ControllerContext>();
    _controller.ControllerContext.HttpContext = _request;

    A.CallTo(() => _controller.Request).Returns(_request); 

    var result = _controller.Edit(1) as RedirectToRouteResult;
}

我总是把Request.IsAjaxRequest() 当作假的。对此非常感谢任何帮助。谢谢

【问题讨论】:

  • 我正在尝试重现,但遇到了大问题。我不是 MVC 人,也许我的部分问题是我没有使用正确的版本(我使用的是 VS2013 附带的任何版本),但 _controller.ControllerContext.HttpContext = _request; 无法编译(HttpRequesteBase 不是RequestContext) 和 _controller.Edit(1) 无法编译,因为 Edit 需要 string。你能指出我哪里出错了,或者解决这个问题,以便它至少可以编译吗?

标签: asp.net-mvc unit-testing fakeiteasy


【解决方案1】:

我设法克服了编译错误,并使用了FakeItEasy Succinctly 第 10 章中的一些信息,这些信息都是关于 ASP.NET MVC 的。

一般来说,ASP.NET MVC 类的设计不是为了让它们容易被伪造,但我有一个测试设置会导致 IsAjaxRequest 返回 true。两个主要障碍是让控制器使用请求对象并确保请求对象返回我们想要的标头。 第一部分并不难,但第二部分要求我们让请求对象使用具体的NameValueCollection。它默认提供的伪造的没有用,因为正确的属性不是虚拟的。幸运的是,使用真正的 NameValueCollection 成功了。

试试这个:

[Fact]
public void Get_Edit_AjaxRequest_ExpectedActionCalled_Blair()
{
    HttpRequestBase _request = A.Fake<HttpRequestBase>();

    // NameValueCollection is effectively unfakeable due to non-virtual properties,
    // but a real one works just fine, so make sure the headers use one of those.
    A.CallTo(() => _request.Headers).Returns(new NameValueCollection());
    _request.Headers["X-Requested-With"] = "XMLHttpRequest";

    var httpContext = A.Fake<HttpContextBase>();
    A.CallTo(() => httpContext.Request).Returns(_request);

    _controller.ControllerContext = new ControllerContext(
        new RequestContext(httpContext, new RouteData()),
        _controller);

    var result = _controller.Edit(1) as RedirectToRouteResult;
}

请注意,在 MVC 框架中会有很多这样的陷阱,继续伪造它们可能会继续令人沮丧。您可能会发现一种更可持续的方法是将尽可能多的逻辑提取到不依赖 MVC 框架的普通旧的可测试业务类中。

【讨论】:

  • 感谢 Blair 提供解决方案.. 以及本书的参考.. 这非常有帮助...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-18
相关资源
最近更新 更多