2015-09-15 7 views
1

Я пишу несколько тестов для AuthorizeAttribute класс, который я написал для своих контроллеров веб-API. Я пытаюсь макет все, что нужно, чтобы быть в состоянии установить следующий ВАР в моем классе AuthorizeAttributeTotalAccess:NSubstitute mock HttpActionDescriptor с ActionName

  1. ActionName = filterContext.ActionDescriptor.ActionName;
  2. controllerName = filterContext.ControllerContext.ControllerDescriptor.ControllerName;
  3. ClaimPrincipal = HttpContext.Current.User as ClaimsPrincipal;

ПРИМЕЧАНИЕ: Я не женат на HttpContext.Current и если есть другой контекст thaat всегда будет иметь его, дайте мне знать.

Мой тест, до сих пор выглядит следующим образом:

using System.Collections.ObjectModel; 
using System.Linq; 
using System.Net; 
using System.Net.Http; 
using System.Security.Claims; 
using System.Security.Principal; 
using System.Threading; 
using System.Web.Http; 
using System.Web.Http.Controllers; 
using BI.Security.Library.Authorization; 
using Microsoft.VisualStudio.TestTools.UnitTesting; 
using NSubstitute; 


namespace AppTest 
{ 
    [TestClass] 
    public class AttributeAuthorize 
    { 
     private AuthorizeAttributeTotalAccess _filter; 
     private HttpActionContext _actionContext; 
     private IPrincipal _originalPrincipal; 

     [TestInitialize] 
     public void SetUp() 
     { 
      var attributes = new Collection<AllowAnonymousAttribute>(); 

      var controllerDescriptor = Substitute.For<HttpControllerDescriptor>(); 
      controllerDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().Returns(attributes); 
      controllerDescriptor.ControllerName = "Template"; 

      var controllerContext = new HttpControllerContext 
      { 
       Request = new HttpRequestMessage(), 
       ControllerDescriptor = controllerDescriptor 
      }; 

      // HOW DO I SET ACTIONNAME HERE??? 
      var actionDescriptor = Substitute.For<HttpActionDescriptor>(); 
      actionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().Returns(attributes); 

      _actionContext = new HttpActionContext(controllerContext, actionDescriptor); 

      _originalPrincipal = Thread.CurrentPrincipal; 
      _filter = new AuthorizeAttributeTotalAccess(); 
     } 

     [TestCleanup] 
     public void TearDown() 
     { 
      Thread.CurrentPrincipal = _originalPrincipal; 
     } 

     [TestMethod] 
     public void Returns_unauthorized_response_if_user_is_not_authenticated() 
     { 
      _filter.OnAuthorization(_actionContext); 

      Assert.IsNotNull(_actionContext.Response); 
      Assert.AreSame(_actionContext.Response.StatusCode, HttpStatusCode.Unauthorized); 
     } 

     [TestMethod] 
     public void Returns_unauthorized_response_if_user_is_authenticated_but_not_in_system_roles() 
     { 
      Thread.CurrentPrincipal = GetTestUser("admin"); 

      _filter.OnAuthorization(_actionContext); 

      Assert.AreSame(_actionContext.Response.StatusCode, HttpStatusCode.Unauthorized); 
     } 

     [TestMethod] 
     public void Short_circuits_request_if_user_is_authenticated_and_in_system_roles() 
     { 
      Thread.CurrentPrincipal = GetTestUser("admin", "ApiWriteUser"); 

      _filter.OnAuthorization(_actionContext); 

      Assert.IsNull(_actionContext.Response); 
     } 

     private IPrincipal GetTestUser(params string[] roles) 
     { 
      var identity = new ClaimsIdentity(new[] {new Claim(ClaimTypes.Name, "Test User")}, "password"); 
      roles.ToList().ForEach(a => identity.AddClaim(new Claim(ClaimTypes.Role, a))); 


      var claimsPrincipal = new ClaimsPrincipal(identity); 

      _actionContext.RequestContext.Principal = claimsPrincipal; 

      return claimsPrincipal; 
     } 
    } 
} 

Что мне не хватает?

Опять же, как я:

  1. Установите ActionName так что он доступен в классе для проверки?
  2. Установить HttpContext.Current, чтобы я мог видеть пользователя?
+0

Для чего это стоит, вместо использования 'HttpContext.Current.User', вместо этого я бы использовал' _actionContext.RequestContext.Principal'. Это легче подделать. – vcsjones

+0

@vcsjones, как вы подделываете _actionContext.RequestContext.Principal? –

ответ

2

Установить имя Action так, чтобы оно было доступно в тестируемом классе?

Я не совсем специалист по NSubstitute (читайте: Я никогда не использовал его), но так как ваш HttpActionDescriptor заглушки/макет, вы должны быть в состоянии окурок возвращаемого значения:

actionDescriptor.ActionName.Return("BLAH"); 

Согласно NSubstitute's documentation, вот как вы возвращаете значение свойства.

Установить HttpContext.Current, чтобы я мог видеть пользователя?

HttpContext.Current имеет сеттер, поэтому вы должны установить его поддельный контекст. Other Stack Overflow answers демонстрируют, как это сделать.

+1

Я пропустил это в документах. Я совершенно новый для NSubstitute. Спасибо, vcsjones! –

Смежные вопросы