如何为模型设置 IPrincipal?

发布于 2024-08-02 11:55:36 字数 464 浏览 2 评论 0原文

我想模拟 IPrincipal,所以我

public Mock<IPrincipal> Principal { get; set; }

在 nunit 的设置中

 Principal = new Mock<IPrincipal>();

做了这个所以这应该是我在 nunit 单元测试中需要的全部内容,但是在我的实际控制器文件中怎么样?

比如我该如何设置?

例如,我有一个membership.Provider

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

Provider = Membership.Provider;

然后在我的控制器中,我只使用了Provider。(无论我需要什么)。

我不确定如何以同样的方式设置主体。

I want to mockup IPrincipal so I did this

public Mock<IPrincipal> Principal { get; set; }

in my setup of my nunit

 Principal = new Mock<IPrincipal>();

So this should be all that I need in my nunit unit test but how about in my actual controller file?

Like how do I set it up?

For example I have a membership.Provider

So what I did was in my controller constructor I did

Provider = Membership.Provider;

So then in my controller I just used Provider.(whatever I need).

I am not sure how to setup the Principal thing in the same way.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

|煩躁 2024-08-09 11:55:36

您在谈论 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);

希望这会有所帮助。

编辑:

仅供参考,Controller 类上的 User 属性来自 HttpContext 对象,如您在此处看到的(这是 User 属性的 getter 方法,从 Reflector 获取 - 您也可以下载 ASP.NET MVC 源代码) :

public IPrincipal User
{
    get
    {
        if (this.HttpContext != null)
        {
            return this.HttpContext.User;
        }
        return null;
    }
}

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

public HttpContextBase HttpContext
{
    get
    {
        if (base.ControllerContext != null)
        {
            return base.ControllerContext.HttpContext;
        }
        return null;
    }
}

因此,到目前为止的所有内容都是“只读”的。我们需要一种方法来“注入”模拟的“用户”。因此,我们检查是否实际上可以通过属性在控制器上注入 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;
    }
}

因此,在这里我们看到 ControllerContext 对象从 RequestContext 对象获取其 HttpContext。因此,这可能解释了我上面所做的事情:

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

经过所有这些魔法之后,如果没有通过 Web 服务器建立实际连接,控制器将不知道您正在调用它。

因此,您可以像往常一样继续在控制器内使用“用户”属性,无需进行任何更改。

Are you talking about ASP.NET MVC? I guess so.

You have to create an instance of the controller and set its RequestContext. You mock the HttpContext of the RequestContext, and inside this HttpContext, you mock its User property, and set it up to your mocked 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);

Hope this helps.

EDIT:

FYI, the User property on the Controller class comes from the HttpContext object, as you can see here (this is the getter method for the User property, obtained from Reflector -- you can download ASP.NET MVC source code as well):

public IPrincipal User
{
    get
    {
        if (this.HttpContext != null)
        {
            return this.HttpContext.User;
        }
        return null;
    }
}

If you now check the HttpContext property, you will see:

public HttpContextBase HttpContext
{
    get
    {
        if (base.ControllerContext != null)
        {
            return base.ControllerContext.HttpContext;
        }
        return null;
    }
}

So, everything until now was "read only". And we need a way to "inject" a mocked "User". So, we check that we can actually inject a ControllerContext object on the controller through a property. We verify how it is obtaining its "HttpContext" object, to know how to properly mock it up:

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;
    }
}

So, here we see that the ControllerContext object obtains it's HttpContext from a RequestContext object. So that might explain what I did above:

  1. Mock an IPrincipal with the data you want,
  2. Mock a HttpContext, and feed it with the IPrincipal,
  3. Mock a RequestContext, and feed it with the HttpContext,
  4. Create an instance of your controller and set it's ControllerContext property to the mocked RequestContext object.

After all this magic, the controller will have no idea that you are calling it without an actual connection being made through a Web Server.

So, you can continue to use your "User" property inside your controller as usual, no changes must be done.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文