unit-test-security-authorization

giuseppe-trisciuoglio/developer-kit · updated Apr 8, 2026

$npx skills add https://github.com/giuseppe-trisciuoglio/developer-kit --skill unit-test-security-authorization
0 commentsdiscussion
summary

Unit testing patterns for Spring Security authorization annotations and role-based access control.

  • Covers @PreAuthorize , @Secured , and @RolesAllowed method-level security with @WithMockUser test fixtures
  • Includes role-based access control (RBAC), expression-based authorization, and custom PermissionEvaluator testing
  • Provides MockMvc patterns for testing secured REST endpoints and parameterized role testing strategies
  • Demonstrates both allow and deny scenarios, owner-based access
skill.md

Unit Testing Security and Authorization

Overview

This skill provides patterns for unit testing Spring Security authorization logic using @PreAuthorize, @Secured, @RolesAllowed, and custom permission evaluators. It covers testing role-based access control (RBAC), expression-based authorization, custom permission evaluators, and verifying access denied scenarios without full Spring Security context.

When to Use

Use this skill when:

  • Testing @PreAuthorize and @Secured method-level security
  • Testing role-based access control (RBAC)
  • Testing custom permission evaluators
  • Verifying access denied scenarios
  • Testing authorization with authenticated principals
  • Want fast authorization tests without full Spring Security context

Instructions

Follow these steps to test Spring Security authorization:

1. Set Up Security Testing Dependencies

Add spring-security-test to your test dependencies:

<dependency>
  <groupId>org.springframework.security</groupId>
  <artifactId>spring-security-test</artifactId>
  <scope>test</scope>
</dependency>

2. Enable Method Security in Test Configuration

@Configuration
@EnableMethodSecurity
class TestSecurityConfig { }

3. Test with @WithMockUser

@Test
@WithMockUser(roles = "ADMIN")
void shouldAllowAdminAccess() {
  assertThatCode(() -> service.deleteUser(1L))
    .doesNotThrowAnyException();
}

@Test
@WithMockUser(roles = "USER")
void shouldDenyUserAccess() {
  assertThatThrownBy(() -> service.deleteUser(1L))
    .isInstanceOf(AccessDeniedException.class);
}

4. Test Custom Permission Evaluators

@Test
void shouldGrantPermissionToOwner() {
  Authentication auth = new UsernamePasswordAuthenticationToken(
    "alice", null, List.of(new SimpleGrantedAuthority("ROLE_USER"))
  );
  Document doc = new Document(1L, "Test", new User("alice"));

  boolean result = evaluator.hasPermission(auth, doc, "WRITE");
  assertThat(result).isTrue();
}

5. Validate Security is Active

If tests pass unexpectedly, add this assertion to verify security is enforced:

@Test
void shouldRejectUnauthorizedWhenSecurityEnabled() {
  assertThatThrownBy(() -> service.deleteUser(1L))
    .isInstanceOf(AccessDeniedException.class);
}

Quick Reference

Annotation Description Example
@PreAuthorize Pre-invocation authorization @PreAuthorize("hasRole('ADMIN')")
@PostAuthorize Post-invocation authorization @PostAuthorize("returnObject.owner == authentication.name")
@Secured Simple role-based security @Secured("ROLE_ADMIN")
@RolesAllowed JSR-250 standard @RolesAllowed({"ADMIN", "MANAGER"})
@WithMockUser Test annotation @WithMockUser(roles = "ADMIN")

Examples

Basic @PreAuthorize Test

@Service
public class UserService {
  @PreAuthorize("hasRole('ADMIN')")
  public void deleteUser(Long userId) {
    // delete logic
  }
}

// Test
@Test
@WithMockUser(roles = "ADMIN")
void shouldAllowAdminToDeleteUser() {
  assertThatCode(() -> service.deleteUser(1L))
    .doesNotThrowAnyException();
}

@Test
@WithMockUser(roles = "USER")
void shouldDenyUserFromDeletingUser() {
  assertThatThrownBy(() -> service.deleteUser(1L))
    .isInstanceOf(AccessDeniedException.class);
}

Expression-Based Security Test

@PreAuthorize("#userId == authentication.principal.id")
public UserProfile getUserProfile(Long userId) {
  // get profile
}

// For custom principal properties, use @WithUserDetails with a custom UserDetailsService
@Test
@WithUserDetails("alice")
void shouldAllowUserToAccessOwnProfile() {
  assertThatCode(() -> service.getUserProfile(1L))
    .doesNotThrowAnyException();
}

Validation tip: If a security test passes unexpectedly, verify that @EnableMethodSecurity is active on the test configuration — a missing annotation causes all @PreAuthorize checks to be bypassed silently.

See references/basic-testing.md for more basic patterns and references/advanced-authorization.md for complex expressions and custom evaluators.

Best Practices

  1. Use @WithMockUser for setting authenticated user context
  2. Test both allow and deny cases for each security rule
  3. Test with different roles to verify role-based decisions
  4. Test expression-based security comprehensively
  5. Mock external dependencies (permission evaluators, etc.)
  6. Test anonymous access separately from authenticated access
  7. Use @EnableGlobalMethodSecurity in configuration for method-level security

Common Pitfalls

  • Forgetting to enable method security in test configuration
  • Not testing both allow and deny scenarios
  • Testing framework code instead of authorization logic
  • Not handling null authentication in tests
  • Mixing authentication and authorization tests unnecessarily

Constraints and Warnings

  • Method security requires proxy: @PreAuthorize works via proxies; direct method calls bypass security
  • @EnableGlobalMethodSecurity: Must be enabled for @PreAuthorize, @Secured to work
  • Role prefix: Spring adds "ROLE_" prefix automatically; use hasRole('ADMIN') not hasRole('ROLE_ADMIN')
  • Authentication context: Security context is thread-local; be careful with async tests
  • @WithMockUser limitations: Creates a simple Authentication; complex auth scenarios need custom setup
  • SpEL expressions: Complex SpEL in @PreAuthorize can be difficult to debug; test thoroughly
  • Performance impact: Method security adds overhead; consider security at layer boundaries

References

Setup and Configuration

Testing Patterns

Advanced Topics

Complete Examples

Discussion

Product Hunt–style comments (not star reviews)
  • No comments yet — start the thread.
general reviews

Ratings

4.662 reviews
  • Min Taylor· Dec 24, 2024

    unit-test-security-authorization fits our agent workflows well — practical, well scoped, and easy to wire into existing repos.

  • Min Gonzalez· Dec 20, 2024

    We added unit-test-security-authorization from the explainx registry; install was straightforward and the SKILL.md answered most questions upfront.

  • Isabella Bhatia· Dec 12, 2024

    Keeps context tight: unit-test-security-authorization is the kind of skill you can hand to a new teammate without a long onboarding doc.

  • Chaitanya Patil· Dec 8, 2024

    unit-test-security-authorization fits our agent workflows well — practical, well scoped, and easy to wire into existing repos.

  • Mateo Patel· Dec 8, 2024

    Registry listing for unit-test-security-authorization matched our evaluation — installs cleanly and behaves as described in the markdown.

  • Piyush G· Nov 27, 2024

    unit-test-security-authorization is among the better-maintained entries we tried; worth keeping pinned for repeat workflows.

  • Arya Patel· Nov 27, 2024

    Useful defaults in unit-test-security-authorization — fewer surprises than typical one-off scripts, and it plays nicely with `npx skills` flows.

  • Rahul Santra· Nov 23, 2024

    unit-test-security-authorization has been reliable in day-to-day use. Documentation quality is above average for community skills.

  • Isabella Chawla· Nov 19, 2024

    I recommend unit-test-security-authorization for anyone iterating fast on agent tooling; clear intent and a small, reviewable surface area.

  • Benjamin Iyer· Nov 15, 2024

    unit-test-security-authorization is among the better-maintained entries we tried; worth keeping pinned for repeat workflows.

showing 1-10 of 62

1 / 7