-
Notifications
You must be signed in to change notification settings - Fork 0
Spring Testing
There are three types of test when developing a Spring application:
- Unit Tests - classic unit tests that do not rely on spring annotations or features. These are the fastest tests.
-
Spring Tests - tests that use the
@ContextConfigurationto initialize the Application Context to load a few specific beans and features. These are slower than traditional unit tests so often referred to as lightweight integration tests. These can include slice tests. -
Spring Integration Tests - tests that use the
@SpringBootTestto initialize the full Application Context. These should be treated as full integration tests as they can be very slow.
ContextConfiguration - A class annotated with this can be considered a lightweight integration test. It is used to target loading specific configuration(s) for use in a test. It is a general Spring feature, and not specific to Spring Boot.
It does involve spring initialization so should be avoided where possible when writing tests, but it is less of an overhead that using @SpringBootTest.
SpringBootTest - A class annotated with this is an integration test. It will load the entire spring Application Context, and consequently will likely include a significant startup cost.
Integration tests should be run judiciously during development. Although it is essential to run them during the build pipeline, particularly before deployment in any environment, they should not be run routinely during day-to-day development.
The SpringBootTest annotation provides the following features:
- Auto Configuration
- Application Properties Loading
- Component Scanning
- Embedded Web Server Support
To make it easier to write lightweight Spring tests that don't initialise the entire Application Context, there are also a set of annotations useful for slice testing:
- @JsonTest - For testing JSON serialization/deserialization.
- @RestClientTest - For testing web REST clients.
- @WebMvcTest - For testing web MVC controllers and components.
- @WebFluxTest - The testing WebFlux (reactive) web controllers and components.
- @JdbcTest - For testing JDBC-based components.
- @DataJpaTest - For testing JPA repositories.
- @DataMongoTest - For testing Spring Data MongoDB repositories.
- @DataRedisTest - For testing Spring Data Redis repositories.
- @DataNeo4jTest - For testing Spring Data Neo4j repositories.
- @DataCassandraTest - For testing Spring Data Cassandra repositories.
- @LdapTest - For testing LDAP integrations.
- @WireMockTest - For testing with WireMock enabled.
JUnit 5 introduced an extension mechanism that allows the registration of one or more extensions for a given test. These are registered using the @ExtendsWith annotation:
-
SpringExtension.class- enable support for Spring, included in @SpringBootTest and most slice test annotations. -
MockitoExtension.class- enable Mockito support. -
WireMockExtension.class- enable WireMock support (included in @WireMockTest). -
SoftAssertionsExtension.class- enable AssertJ soft assertions support.
Maven Library \ spring-boot-starter-test
When writing spring boot tests, you will almost always want to include the Spring Boot Test Starter library. It provides support for the following libraries out-of-the-box:
- Spring Test
- JUnit
- AssertJ
- Hamcrest
- Mockito
- JSON
- XML
This covers most of the standard testing libraries you will need.
When adding test dependencies to a build, it is important to remember to restrict the scope of the dependencies to ensure no test libraries end up getting packaged in the deployment artifacts and just generally to promote loose coupling.
For Maven builds we use the scope tag to restrict libraries to tests.
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency>
For Gradle builds, we use the testImplementation configuration.
dependencies {
testImplementation("org.springframework.boot:spring-boot-starter-test")
testImplementation("org.mockito:mockito-core:5.12.0")
testImplementation("org.junit.jupiter:junit-jupiter-api:5.10.0")
}
Make sure you are familiar with all the fundamental testing annotations used in Spring.
| Annotation | Description |
|---|---|
@SpringBootTest |
An integration test that initialises the full application. |
@ContextConfiguration |
A lightweight integration test that initialises specific beans and features. |
@ExtendsWith |
Used to register any JUnit 5 extension. |
@ActiveProfiles |
Activate specific profiles for the test. |
@TestPropertySource |
Add or override properties for the test. |
@DirtiesContext |
Indicates the Application Context has been 'dirtied' and requires reloading for subsequent tests. |
@MockBean |
A mock bean. |
@SpyBean |
A partial mock over an existing bean. |
@Test |
Marks a method as a test. |
@BeforeEach |
Run a method before each test starts. |
@AfterEach |
Run a method after each test finishes. |
@BeforeAll |
Run a method once before any test starts. |
@AfterAll |
Run a method once after all tests finish. |