我想模拟IPrincipal,所以我做了这个
public Mock<IPrincipal> Principal { get; set; }
在我的nunit设置中
Principal = new Mock<IPrincipal>();
所以这应该是我在我的nunit单元测试中需要的所有东西,但在我的实际控制器文件中怎么样?
我喜欢如何设置它?
例如我有会员资格。提供者
所以我所做的是在我做的控制器构造函数中
Provider = Membership.Provider;
然后在我的控制器中我只使用了Provider。(无论我需要什么)。
我不确定如何以相同的方式设置Principal。
答案 0 :(得分: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);
希望这有帮助。
编辑:
仅供参考,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。这可以解释我上面做了什么:
在完成所有这些魔术之后,如果没有通过Web服务器建立实际连接,控制器将不知道您正在调用它。
因此,您可以像往常一样继续在控制器中使用“用户”属性,不必进行任何更改。