Asp.net

如何為模型設置 IPrincipal?

  • August 22, 2009

我想模擬 IPrincipal 所以我這樣做了

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

在我的 nunit 設置中

Principal = new Mock<IPrincipal>();

所以這應該是我在 nunit 單元測試中所需要的,但是在我的實際控制器文件中呢?

比如我該如何設置?

例如我有一個membership.Provider

所以我所做的是在我的控制器建構子中

Provider = Membership.Provider;

因此,在我的控制器中,我只使用了 Provider。(無論我需要什麼)。

我不確定如何以相同的方式設置 Principal 。

你在談論 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 伺服器建立實際連接。

因此,您可以像往常一樣繼續在控制器中使用“使用者”屬性,無需進行任何更改。

引用自:https://stackoverflow.com/questions/1314370