This article is focused on how to test drive a Spring Boot application using Spring Security. I decided to put this together because there is a lot of Spring involved when using Spring Security and because of that testing can be a little bit difficult and slow.
Full source code can be found here:
Overview
Before test driving, I tried to discover how Spring Security works. There are many ways of creating an authentication system with Spring Security but these are the steps (implementation details) I found to be working for my sample application:
- Create a domain object or entity that implements
UserDetails
- Create a service that implements
UserDetailsService
- Create a Security Configuration class with
@EnableWebSecurity
for endpoint access. - Provide a JWT token generator when login succeeds
- Create a filter which gets
Authorization
header from incoming request and authenticates - Apply the filter created above in the Security Configuration
For test driving approach, outside-in (e.g. controller → service → repository) will be used for this problem. Along test driving, some of the implementation details above will be used.
Dependencies
In this example, JUnit5
will be used as main testing library and JJWT
will be used for generating and parsing JWT tokens.
Sign Up
Sign Up Controller Unit Tests
Sign Up Controller Integration Tests
This can be used to drive out some configuration in SecurityConfiguration
.
This will lead to overriding configure(HttpSecurity)
method.
Login
Login Controller Unit Tests
Token Generator Unit Tests
Login Controller Integration Tests
More tests can be added to validate access to different endpoints to existing integration tests inEndpointAccessTests.java
.
This will lead to implementation changes to allow /login
to previous SecurityConfiguration.java
.
Authentication
Filter Unit Tests
User Service Unit Tests
From here it can noticed that UserDetailsService::loadUserByUsername
is not yet implemented. So it is possible to test drive from here.
Integration tests for applying Filter
Lastly, the endpoints that require authentication need to be tested. We already built sign up and login, so we can make use of them to test the access to authenticated endpoints.
The filter that was implemented above can be added to previousSecurityConfiguration
. This will validate and authenticate the Bearer token in the incoming request.