【问题标题】:Unit Test Custom MVC AuthorizationAttribute单元测试自定义 MVC AuthorizationAttribute
【发布时间】:2017-06-07 14:15:49
【问题描述】:

这个问题与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));

【问题讨论】:

  • 提供可用于重现问题的minimal reproducible example。帮助我们帮助您。不得不去检查另一个问题来尝试拼凑你的测试属性,这使得帮助变得更加困难。不要假设我们已经有相关问题的背景。准确确定您在哪里得到错误。这个问题应该能够独立存在。
  • @Nkosi - 你介意让我知道我错过了什么吗?我已经为这个问题提供了我所拥有的每一段代码,以及我遇到的问题。不知道我还能添加什么?该属性位于问题的顶部。我的测试在底部。我参考了另一个问题,因此阅读知道可能存在重复;而不是让用户尝试基于重复关闭 Q

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


【解决方案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);

//...

这将使您克服最初的障碍。您可能仍需要检查您的安排是否有任何其他未正确安排的依赖项。

【讨论】:

  • 又一个该死的——我这周的这些测试都失败了。可以肯定的是,它们让您对框架有更深入的了解!觉得我也试过了。非常感谢,做到了。是的,再次感谢
  • 请注意。仅基于我在您的测试方法中看到的内容,您将反弹一些更多的空错误。我会让你去解决它们。编码愉快。
  • 是的,我还有其他错误,但那是因为我没有安装控制器。那些我可以更轻松地处理。所有这些单元测试的东西都有助于学习:)
  • 单元测试有助于识别代码设计的好坏。测试代码的难易程度直接关系到代码写得好不好。
猜你喜欢
  • 2013-10-19
  • 2011-11-05
  • 2012-11-15
  • 2018-02-25
  • 2015-01-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多