Asp.net mvc 单元测试自定义授权属性

Asp.net mvc 单元测试自定义授权属性,asp.net-mvc,unit-testing,bdd,authorize-attribute,Asp.net Mvc,Unit Testing,Bdd,Authorize Attribute,我已经编写了一个自定义的claims authorizatize属性,我想对我编写的代码进行单元测试,但是一直找不到我想要的东西 例如,这是我的自定义授权属性类: using System.Collections.Generic; using System.IdentityModel.Tokens.Jwt; using System.Linq; using System.Security.Claims; using System.Web; using System.Web.Mvc; using

我已经编写了一个自定义的claims authorizatize属性,我想对我编写的代码进行单元测试,但是一直找不到我想要的东西

例如,这是我的自定义授权属性类:

using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Web;
using System.Web.Mvc;
using System.Web.Security;
using IPD2.MVC.Interfaces.Providers;
using IPD2.MVC.Providers;

namespace IPD2.MVC.Attribute 
{
    public class ClaimsAuthorizeAttribute : AuthorizeAttribute
    {
        private readonly string _claimValue;
        private readonly string _claimType;
        private readonly ITokenProvider _tokenProvider;

        public ClaimsAuthorizeAttribute(string type, string value)
        {
            _claimType = type;
            _claimValue = value;
            _tokenProvider = new TokenProvider();
        }

        public override void OnAuthorization(AuthorizationContext filterContext)
        {
            var jwt = _tokenProvider.ApiToken as JwtSecurityToken;
            if (jwt == null)
            {
                HandleUnauthorizedRequest(filterContext);
            }
            else
            {
                var claim = jwt.Claims.FirstOrDefault(expr => expr.Value == _claimValue);
                var authCookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];
                if (authCookie != null)
                {
                    var formsAuthenticationTicket = FormsAuthentication.Decrypt(authCookie.Value);
                    if (formsAuthenticationTicket != null && !formsAuthenticationTicket.Expired)
                    {
                        var roles = formsAuthenticationTicket.UserData.Split(',');
                        HttpContext.Current.User = new System.Security.Principal.GenericPrincipal(new FormsIdentity(formsAuthenticationTicket), roles);
                    }
                }

                if (claim != null)
                {
                    base.OnAuthorization(filterContext);
                }
                else
                {
                    HandleUnauthorizedRequest(filterContext);
                }
            }

        }
    }
}
测试代码

  public class GivenCallingClaimAuthorizationAttribute : SpecsFor<ClaimsAuthorizeAttribute>
    {
        //HttpActionContext actionContext;
        //IPrincipal originalPrincipal;

        protected override void Given()
        {

            SUT = new ClaimsAuthorizeAttribute(ClaimTypes.Role, "ImNotAllowedToUseController :(");

        }

        public class WhenUserIsNotAllowedToAccessController : GivenCallingClaimAuthorizationAttribute
        {
            protected override void When()
            {
                SUT.OnAuthorization(
                    new AuthorizationContext()
                );
            }
        }

        [Test]
        public void ThenAssertSomethingBasedOnCodeInTest()
        {
            //todo: some assert
        }
    }
public类给定CallingClaimauAuthorizationAttribute:规范
{
//HttpActionContext-actionContext;
//i原则原创原则;
给定的受保护覆盖无效()
{
SUT=新的ClaimsAuthorizeAttribute(ClaimTypes.Role,“ImNotAllowedToUseController:(”);
}
当用户未安装LowedtoAccessController时的公共类:givenCallingClaimauAuthorization属性
{
受保护的覆盖在()时无效
{
SUT.授权(
新授权上下文()
);
}
}
[测试]
public void TheAssertSomeThingBasedOnCodeIntest()
{
//todo:一些断言
}
}
我已经用BDD框架的规范编写了这个基本的测试类,但我不确定成功测试它需要什么


关于如何测试这一点有什么想法吗?正如您所看到的,我正在测试类本身,而不是具有该属性的控制器。我不确定有什么好的方法来测试这一点。

如果您想执行BDD,请考虑您的类的行为。它应该能够执行什么样的操作

例如,也许它应该:
-授权当前用户
-筛选票证已过期的用户
-为授权用户分配正确的角色
-等等

假设我们要看第二张票,因为它很有趣,我会问你,“你能给我一张票什么时候到期的例子吗?”

然后你说,“是的,超时时间是500毫秒,所以超过这个时间的任何东西都会过期。”或者你说,“这些是足球比赛的门票,每年都会发放。”(我不知道什么是门票,但这段对话可以帮我解决这个问题。)

那么我们可以写一个例子:

Given we've got a handler for unauthorized tickets
Given Fred's ticket expired on 2017-05-14  
And it's now 2017-05-14   
When we try to authenticate Fred  
Then Fred should not be authenticated  
And the handler should be given Fred's details
接下来,我想把这些放在代码中的注释中,以“应该”作为测试的标题。之后,只需设置上下文(在给定的上下文中),将其传递给代码进行练习(时间),并验证结果(然后)

但是,您可以看到您的Specs框架只允许一个给定的!这不是很好,因为我已经确定了几个需要不同上下文的场景。如果您使用Specs的方式使用它,您将不得不为我的每个场景创建一个类,而且它们不太容易阅读

我强烈建议改为使用第二种样式,从给定的、何时开始,然后在注释中开始

问题是,与完整系统BDD场景相比,单元测试的步骤实际上没有被重用多少,在这种场景中,上下文通常会被多次调用以获得不同的功能。一个代码单元(或类)倾向于履行一项职责,或者以这种方式进行重构,并且它的上下文不会因为模拟而流入其他类

所以,我发现,仅仅在评论中给出,什么时候,然后给出就足够了

因此,我建议你改用“老派”的方式做我在本页(底部)看到的事情,从评论开始。看看你是怎么做的

顺便说一句,如果你真的想正确地进行BDD,那么你想用BDD的行为示例来驱动开发,并逐步地填充代码使这些示例工作,而不是把它们写下来。这本书将对你非常有帮助