单元测试自定义MVC AuthorizationAttribute

时间:2017-06-07 14:15:50

标签: c# asp.net-mvc unit-testing

这个问题几乎与ASP.NET MVC unit testing custom AuthorizeAttribute重复 - 但是我无法让我的代码运行而不会遇到同样的NullReferenceException

当我模拟我的控制器时,显然有些东西丢失了。

我的属性很简单 - 看起来像这样:

public override void OnAuthorization(AuthorizationContext filterContext)
{
    if (!base.AuthorizeCore(filterContext.HttpContext))
    {
        filterContext.Controller.TempData.Add("RedirectReason", "Unauthorized");
    }
    base.OnAuthorization(filterContext);
}

我最近的尝试如下。我还尝试了该引用链接上的问题代码,包括向上下文添加项目。

 // Arrange
        Mock<IPrincipal> userMock = new Mock<IPrincipal>();
        Mock<HttpResponseBase> responseMock = new Mock<HttpResponseBase>();
        responseMock.SetupGet(res => res.Cache).Returns(new Mock<HttpCachePolicyBase>().Object);

        Mock<HttpContextBase> contextMock = new Mock<HttpContextBase>(MockBehavior.Strict);
        contextMock.SetupGet(cm => cm.User).Returns(userMock.Object);
        contextMock.SetupGet(cm => cm.Response).Returns(responseMock.Object);
        contextMock.SetupGet(cm => cm.Items).Returns(new Mock<IDictionary>().Object);

        Mock<ControllerContext> controllerContextMock = new Mock<ControllerContext>();
        controllerContextMock.SetupGet(ctx => ctx.HttpContext).Returns(contextMock.Object);

        Mock<ActionDescriptor> actionDesMock = new Mock<ActionDescriptor>();
        actionDesMock.Setup(action => action.GetCustomAttributes(typeof(AllowAnonymousAttribute), true)).Returns(new object[0]);

        // Act
        CustomAuthorizationAttribute cusAtr = new CustomAuthorizationAttribute() { Roles = "TestRole" };

        // Assert
        cusAtr.OnAuthorization(new AuthorizationContext(controllerContextMock.Object, actionDesMock.Object));

我还查看了AuthorizeCore的源代码。

运行时,base.AuthorizeCore(filterContext.HttpContext)上的NullReferenceException

测试失败

无法想象缺少什么。

任何想法?

为了方便起见,根据我们的模型调整的另一个问题的代码是:

    // Arrange
    var httpContext = new Mock<HttpContextBase>();
    Dictionary<object, object> dictionary = new Dictionary<object, object>();
    httpContext.SetupGet(cm => cm.Items).Returns(dictionary);
    Mock<IPrincipal> userMock = new Mock<IPrincipal>();
    httpContext.SetupGet(c => c.User).Returns(() => userMock.Object); 
    var requestBase = new Mock<HttpRequestBase>();
    var headers = new NameValueCollection
    {
       {"Special-Header-Name", "false"}
    };
    requestBase.Setup(x => x.Headers).Returns(headers);
    requestBase.Setup(x => x.HttpMethod).Returns("GET");
    requestBase.Setup(x => x.Url).Returns(new Uri("http://localhost/"));
    requestBase.Setup(x => x.RawUrl).Returns("~/Maintenance/UnExistingMaster");
    requestBase.Setup(x => x.AppRelativeCurrentExecutionFilePath).Returns(() => "~/Maintenance/UnExistingMaster");
    requestBase.Setup(x => x.IsAuthenticated).Returns(() => true);
    httpContext.Setup(x => x.Request).Returns(requestBase.Object);
    var controller = new Mock<ControllerBase>();
    var actionDescriptor = new Mock<ActionDescriptor>();
    var controllerContext = new ControllerContext(httpContext.Object, new RouteData(), controller.Object);

    CustomAuthorizationAttribute cusAtr = new CustomAuthorizationAttribute() { Roles = "TestRole" };

    // Act
    cusAtr.OnAuthorization(new AuthorizationContext(controllerContext, actionDescriptor.Object));

1 个答案:

答案 0 :(得分:1)

您引用了源代码。您是否看过它需要什么以及您设置了什么?你设置了一个主要模拟。大。但身份没有设定。在检查用户是电话

if (!user.Identity.IsAuthenticated) //<-- Identity would be null.

由于未安排Identity,因此无效。

只需创建一个通用主体并使用它。所有必要的依赖项都将为您初始化。

//...

IPrincipal principal = new GenericPrincipal(new GenericIdentity("TestName"), new[] { "TestRole" });

httpContext.SetupGet(c => c.User).Returns(() => principal);

//...

这会让你超越你的初始障碍。您可能仍需要检查您的安排是否有其他未正确安排的依赖项。