Spring Boot
Unit Testing
JWT
Security
Java

Spring Boot Unit Tests with JWT Token Security

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

Introduction

Testing a Spring Boot application that uses JWT security does not have to mean generating real tokens in every test. The best strategy depends on what you are trying to verify. For controller tests, it is often enough to inject an authenticated security context. For filter or token-validation tests, you go one level lower and test the JWT handling itself.

Test the Web Layer with Security Context Support

For controller-level tests, spring-security-test gives you helpers that simulate authenticated requests cleanly.

java
1import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.jwt;
2import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
3import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
4
5import org.junit.jupiter.api.Test;
6import org.springframework.beans.factory.annotation.Autowired;
7import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
8import org.springframework.test.web.servlet.MockMvc;
9
10@WebMvcTest
11class UserControllerTest {
12    @Autowired
13    MockMvc mockMvc;
14
15    @Test
16    void securedEndpointAllowsJwtUser() throws Exception {
17        mockMvc.perform(get("/api/profile").with(jwt()))
18               .andExpect(status().isOk());
19    }
20}

This is usually the cleanest way to test secured controllers because it avoids coupling the test to real token generation.

Test Authorization Rules Deliberately

Once JWT-backed authentication is simulated, the next question is what claims or authorities the request should carry.

java
1mockMvc.perform(
2        get("/api/admin")
3            .with(jwt().authorities(() -> "ROLE_ADMIN"))
4    )
5    .andExpect(status().isOk());

This lets you verify authorization logic directly instead of testing only that "some token exists".

Do Not Confuse Unit Tests with Full Integration Tests

A unit or slice test should usually focus on your controller or security rule behavior, not on proving that a cryptographic JWT library can parse a valid token. That parsing logic belongs in lower-level security tests or integration tests.

If every controller test depends on constructing signed JWT strings, the tests become slower, noisier, and more brittle than they need to be.

Test the Filter Separately When Needed

If your application has a custom JWT filter, test that filter with focused inputs: missing token, malformed token, expired token, and valid token. That is a different test concern from controller authorization.

The design principle is to test each layer at the level where its behavior becomes visible. MockMvc tests can verify protected endpoints. Filter-focused tests can verify token extraction and failure handling.

Mock Dependencies Around Token Verification

If token decoding depends on a service such as a JwtDecoder, mock that dependency in tests where the decoder itself is not the thing under test.

This keeps the tests targeted. You want the test to fail because your security rule is wrong, not because a signing secret or timestamp setup was awkward.

That separation keeps the test suite faster too. Only a small number of integration tests need to exercise the full decoding stack end to end.

That keeps failures easier to localize.

Keep Security Tests Readable

JWT-based applications can accumulate a lot of security detail quickly. Good tests keep the intent obvious: who is the caller, what authority do they have, and should access be granted or denied.

Readable security tests are easier to trust, especially when authorization rules change over time.

Common Pitfalls

  • Generating real signed JWTs in every controller test when a mocked JWT request would be enough.
  • Testing controller behavior and token parsing in the same test layer.
  • Forgetting to model authorities or claims when authorization depends on them.
  • Coupling tests to infrastructure details that are irrelevant to the behavior under test.
  • Writing security tests that show status codes but do not make the caller identity clear.

Summary

  • For controller tests, spring-security-test and jwt() are often the simplest approach.
  • Test authorization rules by controlling authorities and claims explicitly.
  • Keep controller tests separate from low-level token parsing tests.
  • Mock decoders or token services when they are not the focus of the test.
  • Good JWT tests make caller identity and expected access obvious.

Related reading
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

All Rights Reserved.