如何使用FakeItEasy将Request.IsAjaxRequest()模拟为true?

时间:2015-10-16 05:31:43

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

以下是我想要编写单元测试的代码片段:

[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()视为假。任何帮助都非常感谢。感谢

1 个答案:

答案 0 :(得分:2)

我设法混淆了编译错误并使用了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框架的普通旧可测试业务类中。