Testing user if he has a specific authority using AuthorizeAsync() in Xunit-Unit Testing

前端 未结 2 675
时光取名叫无心
时光取名叫无心 2021-01-14 15:25

The question has been Updated for better explanation to the issue I have,

Simply I have this controller,

    [Authorize]
    publi         


        
相关标签:
2条回答
  • 2021-01-14 15:59

    I encountered this issue as well while developing an ASP.NET Core API. My situation was less complex, so not sure if the same solutions is applicable for you.

    Here is my solution

    IAuthorizationService has two methods that are not extensions. One can assume (and I verified) that the extensions are just helpers and will call either one of these methods.

    Task<AuthorizationResult> AuthorizeAsync(ClaimsPrincipal user, object resource, IEnumerable<IAuthorizationRequirement> requirements);
    Task<AuthorizationResult> AuthorizeAsync(ClaimsPrincipal user, object resource, string policyName);
    

    So mocking IAuthorizationService for me was as simple as doing the following:

    var authorizeService = new Mock<IAuthorizationService>();
    authorizeService.Setup(service => service.AuthorizeAsync(It.IsAny<ClaimsPrincipal>(), It.IsAny<object>(), It.IsAny<string>())).ReturnsAsync(AuthorizationResult.Success);
    
    0 讨论(0)
  • 2021-01-14 16:02

    Mock the necessary dependencies for the test. The method under test makes use of IAuthorizationService,IIdeaManagementService,and ITenantService. Everythign else is not needed for this particular test.

    Coupling your code to 3rd party code you don't own and control makes it difficult to test. My suggestion is to abstract that behind an interface you control so you have that flexibility. So change out IAuthorizationService for your own abstraction.

    public interface ICustomAuthorizationService {
         Task<bool> AuthorizeAsync(ClaimsPrincipal user, string policyName);
    }
    

    The implementation would wrap the actual authorization service that uses the extension method

    public class CustomAuthorizationService: ICustomAuthorizationService {
        private readonly IAuthorizationService service;
    
        public CustomAuthorizationService(IAuthorizationService service) {
            this.service = service;
        }
    
        public Task<bool> AuthorizeAsync(ClaimsPrincipal user, string policyName) {
            return service.AuthorizeAsync(user, policyName);
        }
    }
    

    Make sure to register your wrapper. for example.

    services.AddSingleton<ICustomAuthorizationService, CustomAuthorizationService>();
    

    If Identity is already added to service collection then the IAuthorizationService will get injected into your custom service when resolved.

    So now for your test you can mock the interfaces you control and not have to worry about breaking 3rd party code.

    [Theory]
    [InlineData(1)]
    public async void IdeaManager_Should_Return_ViewResult(int _currentTenanatID) {
        // Arrange ..
        var ideaManagementService = new Mock<IIdeaManagementService>();
        var tenantService = new Mock<ITenantService>();
        var authorizationService = new Mock<ICustomAuthorizationService>();
        var sut = new IdeaManagementController(
                         ideaManagementService.Object,
                         tenantService.Object,
                         null,
                         authorizationService.Object,
                         null);
    
         authorizationService
             .Setup(_ => _.AuthorizeAsync(It.IsAny<ClaimsPrincipal>(), "IdeaManagement_Coordinator"))
             .ReturnsAsync(true);
    
         tenantService
             .Setup(_ => _.GetCurrentTenantId())
             .Returns(_currentTenanatID);
    
         var ideas = new //{what ever is your expected return type here}
         ideaManagementService
             .Setup(_ => _.GetByIdeaCoordinator(_currentTenanatID))
             .Returns(ideas);
    
        // Act 
        var _view = await sut.IdeaCoordinator() as ViewResult;
    
        // Assert
        Assert.IsNotNull(_view);
        Assert.IsType(typeof(ViewResult), _view);
        Assert.AreEqual(ideas, view.Model);
    }
    

    This is one example of the draw backs of extension methods as they are static and difficult to test if they hide dependencies.

    0 讨论(0)
提交回复
热议问题