2017-05-15 84 views
0

我写了一个自定义声明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 
     } 
    } 

我已经写了这个基本的测试类与SpecsFor BDD框架,但我不知道它需要什么来成功地测试它。

关于如何测试这个的任何想法?正如你所看到的,我正在测试类本身,而不是具有属性的控制器。我不确定测试此方法的好方法。

回答

0

如果你想做BDD,请考虑你的班级的行为。它应该能够做什么样的事情?

举例来说,或许应该: - 授权当前用户的 - 过滤器的用户,其票证已过期 - 指定授权用户使用正确的角色 - 等

比方说,我们要看看第二个,因为它很有趣。我会问你,“你可以给我一个票证何时可能过期的例子吗?”

然后你会说:“是的,超时时间是500ms,所以超过这个时间的东西都会过期。”或者你说,“这些是足球比赛的门票,每年都会发放。” (我不知道票是什么,但这次谈话会帮助我工作了这一点。)

然后我们可以写一个例子:

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 

下一个我喜欢把这些意见中代码,以“应该”作为测试的标题。之后,这只是一个设置上下文(在给定)的问题,将它传递给你的代码来执行(When)并验证结果(Then)。

但是,您可以看到您的规格框架仅允许给定!这并不好,因为我已经确定了几个需要不同背景的场景。如果您按照使用SpecsFor的方式使用SpecsFor,则必须为每个场景制作一个课程,而且这些课程不会很容易阅读!

我强烈建议使用第二种风格,而不是从评论中的Given,When,Then开始。

事情是,单元测试的步骤并没有被真正重用太多,相比之下,全系统的BDD场景,其中上下文往往被称为几次不同的功能。一个代码单元(或类)倾向于履行一个责任,或者以这种方式进行重构,并且其上下文不会渗入其他类,因为Mocks。

因此,我发现仅仅在评论中有Given,When和Then就足够了。

因此,我建议您切换到“旧学校”的做法,我可以在此页面中看到(下面),并开始评论。看看这是怎么回事。顺便说一句,如果你真的想要正确地做BDD,那么你想驱动的发展与它的行为的例子,并增量填写代码,使这些例子的工作,而不是写他们下。这本书"Growing Object Oriented Software, Guided By Tests"将会对你非常有帮助。