如何为模型设置IPrincipal?

cho*_*bo2 10 asp.net nunit moq

我想模拟IPrincipal所以我这样做了

public Mock<IPrincipal> Principal { get; set; }
Run Code Online (Sandbox Code Playgroud)

在我的nunit设置中

 Principal = new Mock<IPrincipal>();
Run Code Online (Sandbox Code Playgroud)

所以这应该是我在我的nunit单元测试中需要的所有东西,但在我的实际控制器文件中怎么样?

我怎么设置它?

例如,我有一个Membership.Provider

所以我做的是在我的控制器构造函数中

Provider = Membership.Provider;
Run Code Online (Sandbox Code Playgroud)

那么在我的控制器中我只使用了Provider.(无论我需要什么).

我不知道如何以相同的方式设置Principal.

Bru*_*eis 20

你在谈论ASP.NET MVC吗?大概吧.

您必须创建控制器的实例并设置其RequestContext.您模拟RequestContext的HttpContext,并在此HttpContext中,您模拟其User属性,并将其设置为您的模拟IPrincipal:

var principal = new Moq.Mock<IPrincipal>();
// ... mock IPrincipal as you wish

var httpContext = new Moq.Mock<HttpContextBase>();
httpContext.Setup(x => x.User).Returns(principal.Object);
// ... mock other httpContext's properties, methods, as needed

var reqContext = new RequestContext(httpContext.Object, new RouteData());

// now create the controller:
var controller = new MyController();
controller.ControllerContext =
    new ControllerContext(reqContext, controller);
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助.

编辑:

FYI,Controller类的User属性来自HttpContext对象,如此处所示(这是User属性的getter方法,从Reflector获取 - 您也可以下载ASP.NET MVC源代码):

public IPrincipal User
{
    get
    {
        if (this.HttpContext != null)
        {
            return this.HttpContext.User;
        }
        return null;
    }
}
Run Code Online (Sandbox Code Playgroud)

如果现在检查HttpContext属性,您将看到:

public HttpContextBase HttpContext
{
    get
    {
        if (base.ControllerContext != null)
        {
            return base.ControllerContext.HttpContext;
        }
        return null;
    }
}
Run Code Online (Sandbox Code Playgroud)

因此,到目前为止,所有内容都是"只读".我们需要一种"注入"模拟"用户"的方法.因此,我们检查我们是否可以通过属性在控制器上实际注入一个ControllerContext对象.我们验证它是如何获取它的"HttpContext"对象,知道如何正确地模拟它:

public virtual HttpContextBase HttpContext
{
    get
    {
        if (this._httpContext == null)
        {
            this._httpContext = (this._requestContext != null) ? this._requestContext.HttpContext : new EmptyHttpContext();
        }
        return this._httpContext;
    }
    set
    {
        this._httpContext = value;
    }
}
Run Code Online (Sandbox Code Playgroud)

因此,在这里我们看到ControllerContext对象从RequestContext对象获取它的HttpContext.这可以解释我上面做了什么:

  1. 使用您想要的数据模拟IPrincipal,
  2. 模拟一个HttpContext,并用IPrincipal提供它,
  3. 模拟一个RequestContext,并用HttpContext提供它,
  4. 创建控制器的实例,并将其ControllerContext属性设置为模拟的RequestContext对象.

在所有这些魔力之后,如果没有通过Web服务器进行实际连接,控制器将不知道您正在调用它.

因此,您可以像往常一样继续在控制器内使用"用户"属性,不必进行任何更改.