Testing Spring Boot Applications
- Testing Spring Boot Applications
- Detecting Web Application Type
- Detecting Test Configuration
- Using the Test Configuration Main Method
- Excluding Test Configuration
- Using Application Arguments
- Testing With a Mock Environment
- Testing With a Running Server
- Customizing RestTestClient
- Customizing WebTestClient
- Using JMX
- Using Observations
- Using Metrics
| This version is still in development and is not considered stable yet. For the latest stable version, please use Spring Boot 4.1.1! |
A Spring Boot application is a Spring ApplicationContext, so nothing very special has to be done to test it beyond what you would normally do with a vanilla Spring context.
External properties, logging, and other features of Spring Boot are installed in the context by default only if you use SpringApplication to create it. |
Spring Boot provides a @SpringBootTest annotation, which can be used as an alternative to the standard spring-test @ContextConfiguration annotation when you need Spring Boot features.
The annotation works by creating the [ApplicationContext](https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/context/ApplicationContext.html) used in your tests through [SpringApplication](https://docs.spring.io/spring-boot/4.1.3-SNAPSHOT/api/java/org/springframework/boot/SpringApplication.html).
In addition to @SpringBootTest a number of other annotations are also provided for testing more specific slices of an application.
If you are using JUnit 4, do not forget to also add @RunWith(SpringRunner.class) to your test, otherwise the annotations will be ignored. If you are using JUnit 6, there is no need to add the equivalent @ExtendWith(SpringExtension.class) as @SpringBootTest and the other @…Test annotations are already annotated with it. |
By default, @SpringBootTest will not start a server.
You can use the webEnvironment attribute of @SpringBootTest to further refine how your tests run:
MOCK(Default) : Loads a webApplicationContextand provides a mock web environment. Embedded servers are not started when using this annotation. If a web environment is not available on your classpath, this mode transparently falls back to creating a regular non-webApplicationContext. It can be used in conjunction with@AutoConfigureMockMvc,@AutoConfigureRestTestClient, or@AutoConfigureWebTestClientfor mock-based testing of your web application.RANDOM_PORT: Loads aWebServerApplicationContextand provides a real web environment. Embedded servers are started and listen on a random port.DEFINED_PORT: Loads aWebServerApplicationContextand provides a real web environment. Embedded servers are started and listen on a defined port (from yourapplication.properties) or on the default port of8080.NONE: Loads anApplicationContextby usingSpringApplicationbut does not provide any web environment (mock or otherwise).
If your test is @Transactional, it rolls back the transaction at the end of each test method by default. However, as using this arrangement with either RANDOM_PORT or DEFINED_PORT implicitly provides a real servlet environment, the HTTP client and server run in separate threads and, thus, in separate transactions. Any transaction initiated on the server does not roll back in this case. |
@SpringBootTest with webEnvironment = WebEnvironment.RANDOM_PORT will also start the management server on a separate random port if your application uses a different port for the management server. |
Detecting Web Application Type
If Spring MVC is available, a regular MVC-based application context is configured. If you have only Spring WebFlux, we will detect that and configure a WebFlux-based application context instead.
If both are present, Spring MVC takes precedence.
If you want to test a reactive web application in this scenario, you must set the spring.main.web-application-type property:
- Java
- Kotlin
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest(properties = "spring.main.web-application-type=reactive")
class MyWebFluxTests {
// ...
}
import org.springframework.boot.test.context.SpringBootTest
@SpringBootTest(properties = ["spring.main.web-application-type=reactive"])
class MyWebFluxTests {
// ...
}
Detecting Test Configuration
If you are familiar with the Spring Test Framework, you may be used to using @ContextConfiguration(classes=…) in order to specify which Spring @Configuration to load.
Alternatively, you might have often used nested @Configuration classes within your test.
When testing Spring Boot applications, this is often not required.
Spring Boot’s @*Test annotations search for your primary configuration automatically whenever you do not explicitly define one.
The search algorithm works up from the package that contains the test until it finds a class annotated with @SpringBootApplication or @SpringBootConfiguration.
As long as you structured your code in a sensible way, your main configuration is usually found.
If you use a test annotation to test a more specific slice of your application, you should avoid adding configuration settings that are specific to a particular area on the main method’s application class. The underlying component scan configuration of @SpringBootApplication defines exclude filters that are used to make sure slicing works as expected. If you are using an explicit @ComponentScan directive on your @SpringBootApplication-annotated class, be aware that those filters will be disabled. If you are using slicing, you should define them again. |
If you want to customize the primary configuration, you can use a nested @TestConfiguration class.
Unlike a nested @Configuration class, which would be used instead of your application’s primary configuration, a nested @TestConfiguration class is used in addition to your application’s primary configuration.
| Spring’s test framework caches application contexts between tests. Therefore, as long as your tests share the same configuration (no matter how it is discovered), the potentially time-consuming process of loading the context happens only once. |
Using the Test Configuration Main Method
Typically the test configuration discovered by @SpringBootTest will be your main @SpringBootApplication.
In most well structured applications, this configuration class will also include the main method used to launch the application.
For example, the following is a very common code pattern for a typical Spring Boot application:
- Java
- Kotlin
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.docs.using.structuringyourcode.locatingthemainclass.MyApplication
import org.springframework.boot.runApplication
@SpringBootApplication
class MyApplication
fun main(args: Array<String>) {
runApplication<MyApplication>(*args)
}
In the example above, the main method doesn’t do anything other than delegate to SpringApplication.run(Class, String...).
It is, however, possible to have a more complex main method that applies customizations before calling SpringApplication.run(Class, String...).
For example, here is an application that changes the banner mode and sets additional profiles:
- Java
- Kotlin
import org.springframework.boot.Banner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication application = new SpringApplication(MyApplication.class);
application.setBannerMode(Banner.Mode.OFF);
application.setAdditionalProfiles("myprofile");
application.run(args);
}
}
import org.springframework.boot.Banner
import org.springframework.boot.runApplication
import org.springframework.boot.autoconfigure.SpringBootApplication
@SpringBootApplication
class MyApplication
fun main(args: Array<String>) {
runApplication<MyApplication>(*args) {
setBannerMode(Banner.Mode.OFF)
setAdditionalProfiles("myprofile")
}
}
Since customizations in the main method can affect the resulting ApplicationContext, it’s possible that you might also want to use the main method to create the ApplicationContext used in your tests.
By default, @SpringBootTest will not call your main method, and instead the class itself is used directly to create the ApplicationContext
If you want to change this behavior, you can change the useMainMethod attribute of @SpringBootTest to SpringBootTest.UseMainMethod.ALWAYS or SpringBootTest.UseMainMethod.WHEN_AVAILABLE.
When set to ALWAYS, the test will fail if no main method can be found.
When set to WHEN_AVAILABLE the main method will be used if it is available, otherwise the standard loading mechanism will be used.
For example, the following test will invoke the main method of MyApplication in order to create the ApplicationContext.
If the main method sets additional profiles then those will be active when the ApplicationContext starts.
- Java
- Kotlin
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.UseMainMethod;
@SpringBootTest(useMainMethod = UseMainMethod.ALWAYS)
class MyApplicationTests {
@Test
void exampleTest() {
// ...
}
}
import org.junit.jupiter.api.Test
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.boot.test.context.SpringBootTest.UseMainMethod
@SpringBootTest(useMainMethod = UseMainMethod.ALWAYS)
class MyApplicationTests {
@Test
fun exampleTest() {
// ...
}
}
Excluding Test Configuration
If your application uses component scanning (for example, if you use @SpringBootApplication or @ComponentScan), you may find top-level configuration classes that you created only for specific tests accidentally get picked up everywhere.
As we have seen earlier, @TestConfiguration can be used on an inner class of a test to customize the primary configuration.
@TestConfiguration can also be used on a top-level class. Doing so indicates that the class should not be picked up by scanning.
You can then import the class explicitly where it is required, as shown in the following example:
- Java
- Kotlin
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Import;
@SpringBootTest
@Import(MyTestsConfiguration.class)
class MyTests {
@Test
void exampleTest() {
// ...
}
}
import org.junit.jupiter.api.Test
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.context.annotation.Import
@SpringBootTest
@Import(MyTestsConfiguration::class)
class MyTests {
@Test
fun exampleTest() {
// ...
}
}
If you directly use @ComponentScan (that is, not through @SpringBootApplication) you need to register the TypeExcludeFilter with it. See the TypeExcludeFilter API documentation for details. |
An imported @TestConfiguration is processed earlier than an inner-class @TestConfiguration and an imported @TestConfiguration will be processed before any configuration found through component scanning. Generally speaking, this difference in ordering has no noticeable effect but it is something to be aware of if you’re relying on bean overriding. |
Using Application Arguments
If your application expects arguments, you can
have @SpringBootTest inject them using the args attribute.
- Java
- Kotlin
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.test.context.SpringBootTest;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(args = "--app.test=one")
class MyApplicationArgumentTests {
@Test
void applicationArgumentsPopulated(@Autowired ApplicationArguments args) {
assertThat(args.getOptionNames()).containsOnly("app.test");
assertThat(args.getOptionValues("app.test")).containsOnly("one");
}
}
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.ApplicationArguments
import org.springframework.boot.test.context.SpringBootTest
@SpringBootTest(args = ["--app.test=one"])
class MyApplicationArgumentTests {
@Test
fun applicationArgumentsPopulated(@Autowired args: ApplicationArguments) {
assertThat(args.optionNames).containsOnly("app.test")
assertThat(args.getOptionValues("app.test")).containsOnly("one")
}
}
Testing With a Mock Environment
By default, @SpringBootTest does not start the server but instead sets up a mock environment for testing web endpoints.
With Spring MVC, we can query our web endpoints using MockMvc.
The following integrations are available:
- The regular
MockMvcthat uses Hamcrest. MockMvcTesterthat wrapsMockMvcand uses AssertJ.RestTestClientwhereMockMvcis plugged in as the server to handle requests with.WebTestClientwhereMockMvcis plugged in as the server to handle requests with.
The following example showcases the available integrations:
- Java
- Kotlin
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.resttestclient.autoconfigure.AutoConfigureRestTestClient;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.webmvc.test.autoconfigure.AutoConfigureMockMvc;
import org.springframework.boot.webtestclient.autoconfigure.AutoConfigureWebTestClient;
import org.springframework.test.web.reactive.server.WebTestClient;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.assertj.MockMvcTester;
import org.springframework.test.web.servlet.client.RestTestClient;
import org.springframework.test.web.servlet.client.RestTestClient.ResponseSpec;
import org.springframework.test.web.servlet.client.assertj.RestTestClientResponse;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@SpringBootTest
@AutoConfigureMockMvc
@AutoConfigureRestTestClient
@AutoConfigureWebTestClient
class MyMockMvcTests {
@Test
void testWithMockMvc(@Autowired MockMvc mvc) throws Exception {
mvc.perform(get("/"))
.andExpect(status().isOk())
.andExpect(content().string("Hello World"));
}
@Test // If AssertJ is on the classpath, you can use MockMvcTester
void testWithMockMvcTester(@Autowired MockMvcTester mvc) {
assertThat(mvc.get().uri("/"))
.hasStatusOk()
.hasBodyTextEqualTo("Hello World");
}
@Test
void testWithRestTestClient(@Autowired RestTestClient restClient) {
restClient
.get().uri("/")
.exchange()
.expectStatus().isOk()
.expectBody(String.class).isEqualTo("Hello World");
}
@Test // If you prefer AssertJ, dedicated assertions are available
void testWithRestTestClientAssertJ(@Autowired RestTestClient restClient) {
ResponseSpec spec = restClient.get().uri("/").exchange();
RestTestClientResponse response = RestTestClientResponse.from(spec);
assertThat(response).hasStatusOk()
.bodyText().isEqualTo("Hello World");
}
@Test // If Spring WebFlux is on the classpath
void testWithWebTestClient(@Autowired WebTestClient webClient) {
webClient
.get().uri("/")
.exchange()
.expectStatus().isOk()
.expectBody(String.class).isEqualTo("Hello World");
}
}
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.resttestclient.autoconfigure.AutoConfigureRestTestClient
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.boot.webmvc.test.autoconfigure.AutoConfigureMockMvc
import org.springframework.boot.webtestclient.autoconfigure.AutoConfigureWebTestClient
import org.springframework.test.web.reactive.server.WebTestClient
import org.springframework.test.web.reactive.server.expectBody
import org.springframework.test.web.servlet.MockMvc
import org.springframework.test.web.servlet.assertj.MockMvcTester
import org.springframework.test.web.servlet.client.RestTestClient
import org.springframework.test.web.servlet.client.assertj.RestTestClientResponse
import org.springframework.test.web.servlet.client.expectBody
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get
import org.springframework.test.web.servlet.result.MockMvcResultMatchers.content
import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status
@SpringBootTest
@AutoConfigureMockMvc
@AutoConfigureRestTestClient
@AutoConfigureWebTestClient
class MyMockMvcTests {
@Test
fun testWithMockMvc(@Autowired mvc: MockMvc) {
mvc.perform(get("/"))
.andExpect(status().isOk())
.andExpect(content().string("Hello World"))
}
@Test // If AssertJ is on the classpath, you can use MockMvcTester
fun testWithMockMvcTester(@Autowired mvc: MockMvcTester) {
assertThat(mvc.get().uri("/")).hasStatusOk()
.hasBodyTextEqualTo("Hello World")
}
@Test
fun testWithRestTestClient(@Autowired webClient: RestTestClient) {
webClient
.get().uri("/")
.exchange()
.expectStatus().isOk
.expectBody<String>().isEqualTo("Hello World")
}
@Test // If you prefer AssertJ, dedicated assertions are available
fun testWithRestTestClientAssertJ(@Autowired webClient: RestTestClient) {
val spec = webClient.get().uri("/").exchange()
val response = RestTestClientResponse.from(spec)
assertThat(response).hasStatusOk().bodyText().isEqualTo("Hello World")
}
@Test // If Spring WebFlux is on the classpath
fun testWithWebTestClient(@Autowired webClient: WebTestClient) {
webClient
.get().uri("/")
.exchange()
.expectStatus().isOk
.expectBody<String>().isEqualTo("Hello World")
}
}
If you want to focus only on the web layer and not start a complete ApplicationContext, consider using [@WebMvcTest](https://docs.spring.io/spring-boot/4.1.3-SNAPSHOT/api/java/org/springframework/boot/webmvc/test/autoconfigure/WebMvcTest.html) instead. |
With Spring WebFlux endpoints, you can use WebTestClient as shown in the following example:
- Java
- Kotlin
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.webtestclient.autoconfigure.AutoConfigureWebTestClient;
import org.springframework.test.web.reactive.server.WebTestClient;
@SpringBootTest
@AutoConfigureWebTestClient
class MyMockWebTestClientTests {
@Test
void exampleTest(@Autowired WebTestClient webClient) {
webClient
.get().uri("/")
.exchange()
.expectStatus().isOk()
.expectBody(String.class).isEqualTo("Hello World");
}
}
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.boot.webtestclient.autoconfigure.AutoConfigureWebTestClient
import org.springframework.test.web.reactive.server.WebTestClient
import org.springframework.test.web.reactive.server.expectBody
@SpringBootTest
@AutoConfigureWebTestClient
class MyMockWebTestClientTests {
@Test
fun exampleTest(@Autowired webClient: WebTestClient) {
webClient
.get().uri("/")
.exchange()
.expectStatus().isOk
.expectBody<String>().isEqualTo("Hello World")
}
}
| Testing within a mocked environment is usually faster than running with a full servlet container. However, since mocking occurs at the Spring MVC layer, code that relies on lower-level servlet container behavior cannot be directly tested with MockMvc. For example, Spring Boot’s error handling is based on the “error page” support provided by the servlet container. This means that, whilst you can test your MVC layer throws and handles exceptions as expected, you cannot directly test that a specific custom error page is rendered. If you need to test these lower-level concerns, you can start a fully running server as described in the next section. |
Testing With a Running Server
If you need to start a full running server, we recommend that you use random ports.
If you use @SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT), an available port is picked at random each time your test runs.
The @LocalServerPort annotation can be used to inject the actual port used into your test.
Tests that need to make REST calls to the started server can autowire a
RestTestClient by annotating the test class with @AutoConfigureRestTestClient.
The configured client resolves relative links to the running server and comes with a dedicated API for verifying responses, as shown in the following example:
- Java
- Kotlin
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.resttestclient.autoconfigure.AutoConfigureRestTestClient;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.test.web.servlet.client.RestTestClient;
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@AutoConfigureRestTestClient
class MyRandomPortRestTestClientTests {
@Test
void exampleTest(@Autowired RestTestClient restClient) {
restClient
.get().uri("/")
.exchange()
.expectStatus().isOk()
.expectBody(String.class).isEqualTo("Hello World");
}
}
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.resttestclient.autoconfigure.AutoConfigureRestTestClient
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment
import org.springframework.test.web.servlet.client.RestTestClient
import org.springframework.test.web.servlet.client.expectBody
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@AutoConfigureRestTestClient
class MyRandomPortRestTestClientTests {
@Test
fun exampleTest(@Autowired webClient: RestTestClient) {
webClient
.get().uri("/")
.exchange()
.expectStatus().isOk
.expectBody<String>().isEqualTo("Hello World")
}
}
If you prefer to use AssertJ, dedicated assertions are available from RestTestClientResponse, as shown in the following example:
- Java
- Kotlin
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.resttestclient.autoconfigure.AutoConfigureRestTestClient;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.test.web.servlet.client.RestTestClient;
import org.springframework.test.web.servlet.client.RestTestClient.ResponseSpec;
import org.springframework.test.web.servlet.client.assertj.RestTestClientResponse;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@AutoConfigureRestTestClient
class MyRandomPortRestTestClientAssertJTests {
@Test
void exampleTest(@Autowired RestTestClient restClient) {
ResponseSpec spec = restClient.get().uri("/").exchange();
RestTestClientResponse response = RestTestClientResponse.from(spec);
assertThat(response).hasStatusOk().bodyText().isEqualTo("Hello World");
}
}
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.resttestclient.autoconfigure.AutoConfigureRestTestClient
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment
import org.springframework.test.web.servlet.client.RestTestClient
import org.springframework.test.web.servlet.client.assertj.RestTestClientResponse
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@AutoConfigureRestTestClient
class MyRandomPortRestTestClientAssertJTests {
@Test
fun exampleTest(@Autowired webClient: RestTestClient) {
val exchange = webClient.get().uri("/").exchange()
val response = RestTestClientResponse.from(exchange)
assertThat(response).hasStatusOk()
.bodyText().isEqualTo("Hello World")
}
}
If you have spring-webflux on the classpath, you can also autowire a WebTestClient by annotating the test class with @AutoConfigureWebTestClient.
WebTestClient provides a similar API, as shown in the following example:
- Java
- Kotlin
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.webtestclient.autoconfigure.AutoConfigureWebTestClient;
import org.springframework.test.web.reactive.server.WebTestClient;
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@AutoConfigureWebTestClient
class MyRandomPortWebTestClientTests {
@Test
void exampleTest(@Autowired WebTestClient webClient) {
webClient
.get().uri("/")
.exchange()
.expectStatus().isOk()
.expectBody(String.class).isEqualTo("Hello World");
}
}
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment
import org.springframework.boot.webtestclient.autoconfigure.AutoConfigureWebTestClient
import org.springframework.test.web.reactive.server.WebTestClient
import org.springframework.test.web.reactive.server.expectBody
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@AutoConfigureWebTestClient
class MyRandomPortWebTestClientTests {
@Test
fun exampleTest(@Autowired webClient: WebTestClient) {
webClient
.get().uri("/")
.exchange()
.expectStatus().isOk
.expectBody<String>().isEqualTo("Hello World")
}
}
WebTestClient can also be used with a mock environment, removing the need for a running server, by annotating your test class with @AutoConfigureWebTestClient from spring-boot-webflux-test. |
For certain sliced tests you may need to use the @AutoConfigureWebServer annotation to auto-configure an embedded web server. |
The spring-boot-resttestclient module also provides a TestRestTemplate facility:
- Java
- Kotlin
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.resttestclient.TestRestTemplate;
import org.springframework.boot.resttestclient.autoconfigure.AutoConfigureTestRestTemplate;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@AutoConfigureTestRestTemplate
class MyRandomPortTestRestTemplateTests {
@Test
void exampleTest(@Autowired TestRestTemplate restTemplate) {
String body = restTemplate.getForObject("/", String.class);
assertThat(body).isEqualTo("Hello World");
}
}
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment
import org.springframework.boot.resttestclient.TestRestTemplate
import org.springframework.boot.resttestclient.autoconfigure.AutoConfigureTestRestTemplate
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@AutoConfigureTestRestTemplate
class MyRandomPortTestRestTemplateTests {
@Test
fun exampleTest(@Autowired restTemplate: TestRestTemplate) {
val body = restTemplate.getForObject("/", String::class.java)
assertThat(body).isEqualTo("Hello World")
}
}
To use TestRestTemplate a dependency on spring-boot-restclient is also required.
Take care when adding this dependency as it will enable auto-configuration for RestClient.Builder.
If your main code uses RestClient.Builder, declare the spring-boot-restclient dependency so that it is on your application’s main classpath and not only on its test classpath.
Customizing RestTestClient
To customize the RestTestClient bean, configure a RestTestClientBuilderCustomizer bean.
Any such beans are called with the RestTestClient.Builder that is used to create the RestTestClient.
Customizing WebTestClient
To customize the WebTestClient bean, configure a WebTestClientBuilderCustomizer bean.
Any such beans are called with the WebTestClient.Builder that is used to create the WebTestClient.
Using JMX
As the test context framework caches context, JMX is disabled by default to prevent identical components to register on the same domain.
If such test needs access to an MBeanServer, consider marking it dirty as well:
- Java
- Kotlin
import javax.management.MBeanServer;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.DirtiesContext;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(properties = "spring.jmx.enabled=true")
@DirtiesContext
class MyJmxTests {
@Autowired
private MBeanServer mBeanServer;
@Test
void exampleTest() {
assertThat(this.mBeanServer.getDomains()).contains("java.lang");
// ...
}
}
import javax.management.MBeanServer
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.test.annotation.DirtiesContext
@SpringBootTest(properties = ["spring.jmx.enabled=true"])
@DirtiesContext
class MyJmxTests(@Autowired val mBeanServer: MBeanServer) {
@Test
fun exampleTest() {
assertThat(mBeanServer.domains).contains("java.lang")
// ...
}
}
Using Observations
If you annotate a sliced test with @AutoConfigureTracing from spring-boot-micrometer-tracing-test or with @AutoConfigureMetrics from spring-boot-micrometer-metrics-test, it auto-configures an ObservationRegistry.
The RestTestClient and WebTestClient that are auto-configured for injection in your tests are part of the test harness and are not instrumented. Only the observations of the application itself are recorded: test requests do not show up in client metrics and do not become the root of a trace. To test how your application handles an incoming trace, send the request with a known trace context, such as a W3C traceparent header. The propagation formats that your application accepts are configured with management.tracing.propagation.consume. |
Using Metrics
Regardless of your classpath, meter registries, except the in-memory backed, are not auto-configured when using @SpringBootTest.
If you need to export metrics to a different backend as part of an integration test, annotate it with @AutoConfigureMetrics.
If you annotate a sliced test with @AutoConfigureMetrics, it auto-configures an in-memory [`MeterRegi
(本文超出站点单文档体积上限,已截断)
