Start Learning
Javaneer
Back to stage
Module 5·Testing Spring Applications

Testing Secured Endpoints

Assert that your access rules actually work - authenticated, anonymous, and wrong-role requests.

14 min readIntermediate
On this page

You wrote access rules in the Security module: public reads, LIBRARIAN-only writes, authenticated borrowing. But rules you don't test are rules you only hope work - and a single wrong matcher can leave an endpoint wide open. Spring Security Test lets you assert your rules for real: authenticated, anonymous, and wrong-role requests.

The test support

spring-security-test (included in the test starter) adds request post-processors and annotations that put a fake authenticated user into a MockMvc request. The simplest is @WithMockUser:

@WebMvcTest(BookController.class)
class BookSecurityTest {

    @Autowired MockMvc mvc;
    @MockitoBean BookService service;

    @Test
    void anonymousCannotCreateBooks() throws Exception {
        mvc.perform(post("/api/books").contentType(APPLICATION_JSON).content("{}"))
            .andExpect(status().isUnauthorized());        // 401 — no credentials
    }

    @Test
    @WithMockUser(roles = "MEMBER")
    void memberCannotCreateBooks() throws Exception {
        mvc.perform(post("/api/books").contentType(APPLICATION_JSON).content(validBody))
            .andExpect(status().isForbidden());           // 403 — wrong role
    }

    @Test
    @WithMockUser(roles = "LIBRARIAN")
    void librarianCanCreateBooks() throws Exception {
        mvc.perform(post("/api/books").contentType(APPLICATION_JSON).content(validBody))
            .andExpect(status().isCreated());             // 201 — allowed
    }
}

Three tests capture the whole rule for one endpoint: 401 when anonymous, 403 for the wrong role, 201 for the right one. If someone later fat-fingers the matcher, one of these turns red.

Test the negatives, not just the happy path

The dangerous bug isn't "the librarian can't create a book" - you'd notice that. It's "a member (or anonymous) can." Security tests earn their keep by asserting the requests that must be rejected. Always test the 401 and 403 cases, not only the success.

Rattle every locked door, not just the one you have a key for

A security guard checking a building at night doesn't only confirm their own key opens the front door - they walk the halls and rattle every locked door to make sure it's actually locked. Testing only the allowed request is checking your own key works. The real job is rattling the doors that should be shut: the anonymous and wrong-role requests that must be turned away.

Cover a rule completely

BookVault's rule: DELETE /api/books/{isbn} requires LIBRARIAN. Describe the three test cases that fully cover this rule and the status each should assert - and say which of the three is the one most likely to catch a genuine security regression.

Why is it essential to test the rejected (401/403) cases of a secured endpoint, not just the allowed one?

Key takeaways

  • spring-security-test lets you put a fake authenticated user into MockMvc requests, e.g. with @WithMockUser(roles = ...).
  • Cover each secured endpoint with three cases: anonymous (401), wrong role (403), and correct role (success).
  • The valuable tests are the negatives - proving disallowed requests are actually rejected.
  • A single wrong matcher can open an endpoint; security tests turn red when that happens.
  • Test who is turned away, not only who is let in.
Was this lesson helpful?
Edit this page on GitHub