Course contentsShow
← C#
Lesson 1216 of 1,90811. Identity, Security, and ClaimsFree lesson

Testing Authorization Policies

Create isolated tests to ensure authorization requirements are met by various user profiles.

In this lesson, you will learn how to create isolated unit tests that verify your authorization policies behave correctly across different user profiles.

Why Isolate Authorization Tests?

When we build Policy-Based Authorization, we define complex rules that check if a user has a specific claim, role, or attribute. If we only rely on integration tests (which spin up the whole server), our test suite becomes slow and brittle. Instead, we can extract the core logic—the IAuthorizationRequirement and its corresponding AuthorizationHandler—and test them in isolation.

Testing a Requirement Handler

The AuthorizationHandler<TRequirement> is a class that decides if a request is authorized. To test this without a database or a running API, we mock the AuthorizationHandlerContext. This allows us to "simulate" a user with specific claims and verify if the requirement is satisfied.

Consider a MinimumAgeRequirement that checks a DateOfBirth claim:

[Fact]
public async Task HandleAsync_UserUnder18_SetsRequirementAsFailed()
{
    // Arrange: Create a user with a "young" DOB claim
    var user = new ClaimsPrincipal(new ClaimsIdentity(new[] { 
        new Claim("DateOfBirth", "2010-01-01") 
    }));
    
    var context = new AuthorizationHandlerContext(
        new[] { new MinimumAgeRequirement(18) }, user, null);
    
    var handler = new MinimumAgeHandler();

    // Act
    await handler.HandleAsync(context);

    // Assert: The requirement should not be marked as succeeded
    Assert.False(context.HasSucceeded);
}

Key Considerations for Your Test Suite

  1. Test the Negative Path: Don't just test that an authorized user gains access. Explicitly test that users with missing claims, expired tokens, or insufficient roles are correctly denied.
  2. Use Mocking: You don't need a real HttpContext. By manually constructing a ClaimsPrincipal and an AuthorizationHandlerContext, you isolate the policy logic from the framework's internal plumbing.
  3. Boundary Conditions: If your policy checks for age or spending limits, always test the "off-by-one" scenarios (e.g., exactly 18 years old).

By decoupling your authorization logic from your controllers, you turn security testing into a fast, reliable, and predictable part of your development workflow.

Key Takeaway: By unit testing your AuthorizationHandler classes using mocked contexts, you ensure your security policies are airtight without the performance overhead of full integration tests.