Spring Boot · Lesson 6 of 7

Security & testing

Spring Security basics, password hashing, securing endpoints and writing tests with JUnit and MockMvc.

Spring Security protects your API. Adding the starter secures every endpoint by default; you then configure which URLs are public and which need login or a role.

  • Hash passwords with BCryptPasswordEncoder — never store plain text.
  • Stateless REST APIs usually use JWT or OAuth2 tokens instead of sessions.
  • Use @PreAuthorize("hasRole('ADMIN')") for method-level rules.

Testing

  • Unit tests (JUnit 5 + Mockito) test a service with fake repositories — fast and focused.
  • @WebMvcTest + MockMvc tests controllers without starting a real server.
  • @SpringBootTest starts the full app for integration tests.

Example code

Spring Boot 3 · Java 17+
@Configuration
@EnableMethodSecurity
public class SecurityConfig {
    @Bean
    SecurityFilterChain api(HttpSecurity http) throws Exception {
        return http
            .csrf(csrf -> csrf.disable())                 // stateless token API
            .authorizeHttpRequests(auth -> auth
                .requestMatchers(HttpMethod.GET, "/api/jobs/**").permitAll()
                .requestMatchers("/api/admin/**").hasRole("ADMIN")
                .anyRequest().authenticated())
            .httpBasic(Customizer.withDefaults())          // simple for learning; use JWT in real apps
            .build();
    }

    @Bean
    PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); }
}

@WebMvcTest(JobController.class)
class JobControllerTest {
    @Autowired MockMvc mvc;
    @MockitoBean JobService service;   // @MockBean before Spring Boot 3.4

    @Test
    void returns404WhenJobMissing() throws Exception {
        when(service.get(99L)).thenThrow(new JobNotFoundException(99L));
        mvc.perform(get("/api/jobs/99")).andExpect(status().isNotFound());
    }
}

Output / API response

GET /api/jobs            → 200 OK (public)
POST /api/jobs           → 401 Unauthorized (no credentials)
GET /api/admin/reports   → 403 Forbidden (logged in, not ADMIN)

[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO] BUILD SUCCESS

Generate a project at start.spring.io (Maven, Java 17+, dependencies: Spring Web, Spring Data JPA, H2, Validation), add the code, and run ./mvnw spring-boot:run. Learn the Java tutorial first if you're new to Java. Data is fictional.

Key points

  • Spring Security secures all endpoints until you open them up.
  • Always hash passwords with BCrypt.
  • 401 = not logged in; 403 = logged in but not allowed.
  • Unit-test services with Mockito; test controllers with MockMvc.

Quick check

A logged-in user without the ADMIN role calls an admin endpoint. What status should they get?

Practice task

Write a unit test for JobService.get() using Mockito: one test where the repository returns a job and one where it's empty and the exception is thrown.

Interview corner

How do you secure a Spring Boot REST API?

Add Spring Security, define a SecurityFilterChain that sets public and protected URLs, authenticate with JWT or OAuth2 tokens for stateless APIs, hash passwords with BCrypt, use role checks (@PreAuthorize), enable HTTPS and validate input.

What is the difference between @WebMvcTest and @SpringBootTest?

@WebMvcTest loads only the web layer (controllers, advice, filters) with mocked services, so it's fast. @SpringBootTest loads the whole application context for full integration tests.

Further reading

Official documentation, linked for deeper study. These are outside sites; this lesson's text is our own.

Original lesson written by the InfoparkDaily team · © 2026 InfoparkDaily · Free to learn — no paid course or subscription.