@SpringBootTest Annotation Example
August 26, 2023
On this page, we will learn to create test cases for our Spring Boot application using @SpringBootTest
annotation.
1. The
@SpringBootTest
is used to perform Spring Boot based tests and has default context loader as SpringBootContextLoader
. We can change the default context loader by specifying to @ContextConfiguration(loader= ...)
.
2. If
@SpringBootTest
has not defined classes attribute and we have not used nested @Configuration
in our test class, then @SpringBootTest
automatically searches for @SpringBootConfiguration
.
3. The
@SpringBootTest
has properties attribute that allows to use custom Environment
properties.
4. The
@SpringBootTest
has args attribute that allows to define application arguments.
5. The
@SpringBootTest
supports the different webEnvironment
modes. It can also start fully running web server listening on user defined or random port.
6. In web testing with fully running server, the
@SpringBootTest
registers TestRestTemplate
and WebTestClient
bean as needed.
7. The
@SpringBootTest
works only for Spring Boot application. It means our application should have a class annotated with @SpringBootApplication
or @SpringBootConfiguration
. We can also use @SpringBootTest
with classes attribute specifying @Configuration
classes.
Contents
- 1. Maven Dependencies
- 2. @SpringBootTest Annotation Structure
- 3. JUnit @ExtendWith
- 4. args : Pass Arguments
- 5. classes : Pass Configuration Classes
- 6. properties : Pass Properties as key/value
- 7. webEnvironment : Create Web Application Context
- 8. useMainMethod : Decide using main() method
- 9. Reference
1. Maven Dependencies
Find the Maven dependencies used in in our example.pom.xml
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.1.2</version> </parent> <properties> <context.path>spring-app</context.path> <java.version>17</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-api</artifactId> <version>5.10.0</version> <scope>test</scope> </dependency> </dependencies>
2. @SpringBootTest Annotation Structure
Find the@SpringBootTest
annotation structure from Spring doc.
1. Annotation Declaration :
@Target(value={ElementType.TYPE}) @Retention(value=RetentionPolicy.RUNTIME) @Documented @Inherited @BootstrapWith(value=SpringBootTestContextBootstrapper) @org.junit.jupiter.api.extension.ExtendWith(value={SpringExtension}) public abstract @interface SpringBootTest extends Annotation { ------ }
(a) SpringBootTest.WebEnvironment : Values are DEFINED_PORT, MOCK, RANDOM_PORT and NONE .
(b) SpringBootTest.UseMainMethod : Values are ALWAYS, NEVER and WHEN_AVAILABLE .
3. Elements :
(a) args : Application arguments as an array of
String
.
(b) classes : Component classes as an array of
Class
.
(c) properties : Properties in the form of key=value as an array of
String
that should be added to the Spring Environment before test run.
(d) webEnvironment : The type of web environment to create.
(e) useMainMethod : Decides using main method when creating and running the
SpringApplication
under test.
(f) value : Alias for properties.
3. JUnit @ExtendWith
The@SpringBootTest
is annotated with JUnit @ExtendWith
as
@ExtendWith(SpringExtension.class)
. It means JUnit is already integrated with @SpringBootTest
and we can use JUnit tests in our Spring Boot test cases. The Spring SpringExtension
is used to integrate Spring TestContext
with JUnit Jupiter tests. The test cases written with @ExtendWith
and @ContextConfiguration
can be written directly using @SpringBootTest
in Spring Boot tests.
Find the test code with
@ExtendWith
and @ContextConfiguration
annotation.
package com.concretepage; import static org.assertj.core.api.Assertions.assertThat; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit.jupiter.SpringExtension; import com.concretepage.config.AppConfig; @ExtendWith(SpringExtension.class) @ContextConfiguration(classes = {AppConfig.class}) public class MyAppTest { @Test void myTest() { String name = "Shri Ganesh"; assertThat(name).isEqualTo("Shri Ganesh"); } }
@SpringBootTest
as following.
@SpringBootTest public class MyAppTest { @Test void myTest() { String name = "Shri Ganesh"; assertThat(name).isEqualTo("Shri Ganesh"); } }

4. args : Pass Arguments
In our Spring Boot application, we pass arguments using command line. We can fetch command line arguments in a component implementingCommandLineRunner
. While creating the test cases, we pass the arguments using args
attribute of @SpringBootTest
annotation as an array of String.
@SpringBootTest(args = { "data1", "data2" })
@SpringBootTest(args = { "data1", "data2" }) public class MyAppTest { @Autowired MyCommandLineRunner runner; @Test void myTest() { assertThat(runner.getArgsByIndex(0)).isEqualTo("data1"); } }
MyCommandLineRunner
component code.
@Component public class MyCommandLineRunner implements CommandLineRunner { private String[] myArgs; public void run(String... args) { this.myArgs = args; String strArgs = Arrays.stream(args).collect(Collectors.joining(", ")); System.out.println("Application arguments: " + strArgs); } public String getArgsByIndex(int index) { return this.myArgs[index]; } }
5. classes : Pass Configuration Classes
Theclasses
attribute of @SpringBootTest
is to configure components and JavaConfig classes with Spring boot tests. We need to pass array of Class
to classes
attribute. If we have defined any configuration class, @SpringBootTest
automatically detects and loads it. We can also specify them using classes
attribute.
Suppose we have a class
AppConfig
annotated with @Configuration
annotation, we pass to Spring Boot test as following.
@SpringBootTest(classes = {AppConfig.class}) public class MyAppTest { @Autowired MyService myService; @Test void myTest() { assertThat(myService.getMessage()).isEqualTo("Welcome"); } }
6. properties : Pass Properties as key/value
Usingproperties
attribute of @SpringBootTest
annotation, we can add properties that should be added to Spring Environment before test run. The properties are added in key=value form as an array of String.
Find the example.
@SpringBootTest(properties = {"role=admin", "db=Oracle"}) public class MyAppTest { @Value("${role}") String userRole; @Value("${db}") String database; @Test void test() { assertThat(userRole).isEqualTo("admin"); assertThat(database).isEqualTo("Oracle"); } }
value
attribute is the alias for properties. We can also configure properties using value
attribute as following.
@SpringBootTest({"role=admin", "db=Oracle"}) public class MyAppTest { ------ }
7. webEnvironment : Create Web Application Context
ThewebEnvironment
attribute of @SpringBootTest
is to create the type of web environment when applicable. The value for webEnvironment
is of SpringBootTest.WebEnvironment
enum type as given below.
1. DEFINED_PORT : Creates a reactive web application context without defining server.port Environment property.
2. RANDOM_PORT : Creates reactive or servlet based web application context and sets server.port Environment property listening on random port. We usually use it in conjunctional with
@LocalServerPort
.
3. MOCK : Creates
a. Web application context with mock servlet environment if servlet APIs are on the classpath.
b. Reactive web application context if Spring WebFlux is on the classpath.
c. Regular application context otherwise.
The
MOCK
web environment is default value for webEnvironment
attribute.
4. NONE : Creates application context setting web application type to
WebApplicationType.NONE
.
Example-1:
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) public class MyAppTest { @LocalServerPort private int serverPort; @Test public void myTest(){ assertThat(serverPort > 0).isTrue(); } }
@SpringBootTest(webEnvironment = WebEnvironment.DEFINED_PORT, properties = {"server.port=2010"}) public class MyAppTest { @LocalServerPort private int serverPort; @Test public void myTest(){ assertThat(serverPort == 2010).isTrue(); } }
8. useMainMethod : Decide using main() method
TheuseMainMethod
attribute of @SpringBootTest
decides using main method when creating and running the SpringApplication
under test. Its values are SpringBootTest.UseMainMethod
enum type i.e. ALWAYS, NEVER and WHEN_AVAILABLE . Default value is NEVER. For the value NEVER, main method of application does not run to create SpringApplication
while running test code where as for the value ALWAYS, main method always runs.
Example : Find the main class with main method of our application. Here I am adding a key/value to environment.
@SpringBootApplication public class MyApplication { public static void main(String[] args) { SpringApplication application = new SpringApplication(MyApplication.class); application.setEnvironment(null); Map<String, Object> map = new HashMap<>(); map.put("role", "admin"); application.setDefaultProperties(map); application.run(args); } }
UseMainMethod.ALWAYS
. I am testing the property role that I have set in main method.
@SpringBootTest(useMainMethod = UseMainMethod.ALWAYS) public class MyAppTest { @Autowired Environment environment; @Test public void myTest(){ assertThat(environment.getProperty("role")).isEqualTo("admin"); } }
Now I am using
UseMainMethod.NEVER
.
@SpringBootTest(useMainMethod = UseMainMethod.NEVER) public class MyAppTest { @Autowired Environment environment; @Test public void myTest(){ assertThat(environment.getProperty("role")).isEqualTo("admin"); } }
To make it success, we can set properties using properties attribute. Find the code below.
@SpringBootTest(useMainMethod = UseMainMethod.NEVER, properties = {"role=admin"}) public class MyAppTest { @Autowired Environment environment; @Test public void myTest(){ assertThat(environment.getProperty("role")).isEqualTo("admin"); } }