在测试初始化​​方法中模拟 HttpContext.Current [英] Mock HttpContext.Current in Test Init Method

查看:21
本文介绍了在测试初始化​​方法中模拟 HttpContext.Current的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试向我构建的 ASP.NET MVC 应用程序添加单元测试.在我的单元测试中,我使用以下代码:

I'm trying to add unit testing to an ASP.NET MVC application I have built. In my unit tests I use the following code:

[TestMethod]
public void IndexAction_Should_Return_View() {
    var controller = new MembershipController();
    controller.SetFakeControllerContext("TestUser");

    ...
}

使用以下助手模拟控制器上下文:

With the following helpers to mock the controller context:

public static class FakeControllerContext {
    public static HttpContextBase FakeHttpContext(string username) {
        var context = new Mock<HttpContextBase>();

        context.SetupGet(ctx => ctx.Request.IsAuthenticated).Returns(!string.IsNullOrEmpty(username));

        if (!string.IsNullOrEmpty(username))
            context.SetupGet(ctx => ctx.User.Identity).Returns(FakeIdentity.CreateIdentity(username));

        return context.Object;
    }

    public static void SetFakeControllerContext(this Controller controller, string username = null) {
        var httpContext = FakeHttpContext(username);
        var context = new ControllerContext(new RequestContext(httpContext, new RouteData()), controller);
        controller.ControllerContext = context;
    }
}

此测试类继承自具有以下内容的基类:

This test class inherits from a base class which has the following:

[TestInitialize]
public void Init() {
    ...
}

在这个方法中,它调用一个库(我无法控制)它试图运行以下代码:

Inside this method it calls a library (which i have no control over) which tries to run the following code:

HttpContext.Current.User.Identity.IsAuthenticated

现在您大概可以看到问题所在了.我已经针对控制器设置了假 HttpContext,但没有在这个基本的 Init 方法中设置.单元测试/模拟对我来说很新,所以我想确保我做对了.我模拟 HttpContext 以便它在我的控制器和在我的 Init 方法中调用的任何库共享的正确方法是什么.

Now you can probably see the problem. I have set the fake HttpContext against the controller but not in this base Init method. Unit testing / mocking is very new to me so I want to make sure I get this right. What is the correct way for me to Mock out the HttpContext so that it is shared across my controller and any libraries which are called in my Init method.

推荐答案

HttpContext.Current 返回 System.Web.HttpContext,不扩展 System.Web.HttpContextBase.HttpContextBase 是后来添加的,以解决 HttpContext 难以模拟的问题.这两个类基本上不相关(HttpContextWrapper 是用作它们之间的适配器).

HttpContext.Current returns an instance of System.Web.HttpContext, which does not extend System.Web.HttpContextBase. HttpContextBase was added later to address HttpContext being difficult to mock. The two classes are basically unrelated (HttpContextWrapper is used as an adapter between them).

幸运的是,HttpContext 本身是可伪造的,足以让您替换 IPrincipal(用户)和 IIdentity.

Fortunately, HttpContext itself is fakeable just enough for you do replace the IPrincipal (User) and IIdentity.

以下代码按预期运行,即使在控制台应用程序中:

The following code runs as expected, even in a console application:

HttpContext.Current = new HttpContext(
    new HttpRequest("", "http://tempuri.org", ""),
    new HttpResponse(new StringWriter())
    );

// User is logged in
HttpContext.Current.User = new GenericPrincipal(
    new GenericIdentity("username"),
    new string[0]
    );

// User is logged out
HttpContext.Current.User = new GenericPrincipal(
    new GenericIdentity(String.Empty),
    new string[0]
    );

这篇关于在测试初始化​​方法中模拟 HttpContext.Current的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆