Skip to content

Spring Testing

Robin Drew edited this page May 27, 2025 · 19 revisions

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 @ContextConfiguration to 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 @SpringBootTest to initialize the full Application Context. These should be treated as full integration tests as they can be very slow.

ContextConfiguration

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

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

Slice Tests

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 Extensions

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.

Spring Boot Starter Test Library

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.

Build Configuration

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.

Maven Build Configuration

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>

Gradle Build Configuration

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")
}

Annotation Summary

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.

Clone this wiki locally