Spring Boot provides a number of utilities and annotations to help when testing your
application. Test support is provided by two modules; spring-boot-test
contains core
items, and spring-boot-test-autoconfigure
supports auto-configuration for tests.
Most developers will just use the spring-boot-starter-test
‘Starter’ which
imports both Spring Boot test modules as well has JUnit, AssertJ, Hamcrest and a number
of other useful libraries.
If you use the
spring-boot-starter-test
‘Starter’ (in the test
scope
), you will find
the following provided libraries:
These are common libraries that we generally find useful when writing tests. You are free to add additional test dependencies of your own if these don’t suit your needs.
One of the major advantages of dependency injection is that it should make your code
easier to unit test. You can simply instantiate objects using the new
operator without
even involving Spring. You can also use mock objects instead of real dependencies.
Often you need to move beyond ‘unit testing’ and start ‘integration testing’ (with
a Spring ApplicationContext
actually involved in the process). It’s useful to be able
to perform integration testing without requiring deployment of your application or
needing to connect to other infrastructure.
The Spring Framework includes a dedicated test module for just such integration testing.
You can declare a dependency directly to org.springframework:spring-test
or use the
spring-boot-starter-test
‘Starter’ to pull it in transitively.
If you have not used the spring-test
module before you should start by reading the
relevant section of the Spring Framework reference
documentation.
A Spring Boot application is just 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.
One thing to watch out for though is that the external properties, logging and other
features of Spring Boot are only installed in the context by default 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
used
in your tests via SpringApplication
.
You can use the webEnvironment
attribute of @SpringBootTest
to further refine
how your tests will run:
MOCK
— Loads a WebApplicationContext
and provides a mock servlet environment.
Embedded servlet containers are not started when using this annotation. If servlet
APIs are not on your classpath this mode will transparently fallback to creating a
regular non-web ApplicationContext
. Can be used in conjunction with
@AutoConfigureMockMvc
for MockMvc
-based testing of your application.RANDOM_PORT
— Loads an ServletWebServerApplicationContext
and provides a real
servlet environment. Embedded servlet containers are started and listening on a random
port.DEFINED_PORT
— Loads an ServletWebServerApplicationContext
and provides a real
servlet environment. Embedded servlet containers are started and listening on a defined
port (i.e from your application.properties
or on the default port 8080
).NONE
— Loads an ApplicationContext
using SpringApplication
but does not provide
any servlet environment (mock or otherwise).Note | |
---|---|
If your test is |
Note | |
---|---|
In addition to |
Tip | |
---|---|
Don’t forget to also add |
If you’re 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 will search for your primary configuration
automatically whenever you don’t explicitly define one.
The search algorithm works up from the package that contains the test until it finds a
@SpringBootApplication
or @SpringBootConfiguration
annotated class. As long as you’ve
structured your code in a sensible way your main
configuration is usually found.
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
will be used in addition to your application’s primary configuration.
Note | |
---|---|
Spring’s test framework will cache application contexts between tests. Therefore, as long as your tests share the same configuration (no matter how it’s discovered), the potentially time consuming process of loading the context will only happen once. |
If your application uses component scanning, for example if you use
@SpringBootApplication
or @ComponentScan
, you may find top-level configuration classes
created only for specific tests accidentally get picked up everywhere.
As we have seen above,
@TestConfiguration
can be used on an inner class of a test to customize the primary
configuration. When placed on a top-level class, @TestConfiguration
indicates that
classes in src/test/java
should not be picked up by scanning. You can then import that
class explicitly where it is required:
@RunWith(SpringRunner.class) @SpringBootTest @Import(MyTestsConfiguration.class) public class MyTests { @Test public void exampleTest() { ... } }
Note | |
---|---|
If you directly use |
If you need to start a full running server for tests, we recommend that you use random
ports. If you use @SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT)
an available port will be picked at random each time your test runs.
The @LocalServerPort
annotation can be used to
inject the actual port used into your test.
For convenience, tests that need to make REST calls to the started server can additionally
@Autowire
a TestRestTemplate
which will resolve relative links to the running server.
import org.junit.Test; import org.junit.runner.RunWith; 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.test.web.client.TestRestTemplate; import org.springframework.test.context.junit4.SpringRunner; import static org.assertj.core.api.Assertions.assertThat; @RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) public class RandomPortExampleTests { @Autowired private TestRestTemplate restTemplate; @Test public void exampleTest() { String body = this.restTemplate.getForObject("/", String.class); assertThat(body).isEqualTo("Hello World"); } }
It’s sometimes necessary to mock certain components within your application context when running tests. For example, you may have a facade over some remote service that’s unavailable during development. Mocking can also be useful when you want to simulate failures that might be hard to trigger in a real environment.
Spring Boot includes a @MockBean
annotation that can be used to define a Mockito mock
for a bean inside your ApplicationContext
. You can use the annotation to add new beans,
or replace a single existing bean definition. The annotation can be used directly on test
classes, on fields within your test, or on @Configuration
classes and fields. When used
on a field, the instance of the created mock will also be injected. Mock beans are
automatically reset after each test method.
Note | |
---|---|
This feature is automatically enabled as long as your test uses one of Spring Boot’s
test annotations (i.e. @TestExecutionListeners(MockitoTestExecutionListener.class) |
Here’s a typical example where we replace an existing RemoteService
bean with a mock
implementation:
import org.junit.*; import org.junit.runner.*; import org.springframework.beans.factory.annotation.*; import org.springframework.boot.test.context.*; import org.springframework.boot.test.mock.mockito.*; import org.springframework.test.context.junit4.*; import static org.assertj.core.api.Assertions.*; import static org.mockito.BDDMockito.*; @RunWith(SpringRunner.class) @SpringBootTest public class MyTests { @MockBean private RemoteService remoteService; @Autowired private Reverser reverser; @Test public void exampleTest() { // RemoteService has been injected into the reverser bean given(this.remoteService.someCall()).willReturn("mock"); String reverse = reverser.reverseSomeCall(); assertThat(reverse).isEqualTo("kcom"); } }
Additionally you can also use @SpyBean
to wrap any existing bean with a Mockito spy
.
See the Javadoc for full details.
Spring Boot’s auto-configuration system works well for applications, but can sometimes be a little too much for tests. It’s often helpful to load only the parts of the configuration that are required to test a ‘slice’ of your application. For example, you might want to test that Spring MVC controllers are mapping URLs correctly, and you don’t want to involve database calls in those tests; or you might be wanting to test JPA entities, and you’re not interested in web layer when those tests run.
The spring-boot-test-autoconfigure
module includes a number of annotations that can be
used to automatically configure such ‘slices’. Each of them works in a similar way,
providing a @…Test
annotation that loads the ApplicationContext
and one or
more @AutoConfigure…
annotations that can be used to customize auto-configuration
settings.
Note | |
---|---|
Each slice loads a very restricted set of auto-configuration classes. If you need to
exclude one of them, most |
Tip | |
---|---|
It’s also possible to use the |
To test that Object JSON serialization and deserialization is working as expected you can
use the @JsonTest
annotation. @JsonTest
will auto-configure the available supported
json mapper:
ObjectMapper
, any @JsonComponent
beans and any Jackson Modules
Gson
Jsonb
If you need to configure elements of the auto-configuration you can use the
@AutoConfigureJsonTesters
annotation.
Spring Boot includes AssertJ based helpers that work with the JSONassert and JsonPath
libraries to check that JSON is as expected. The JacksonTester
, GsonTester
,
JsonbTester
and BasicJsonTester
classes can be used for Jackson, Gson, Jsonb and
Strings respectively. Any helper fields on the test class can be @Autowired
when using
@JsonTest
.
import org.junit.*; import org.junit.runner.*; import org.springframework.beans.factory.annotation.*; import org.springframework.boot.test.autoconfigure.json.*; import org.springframework.boot.test.context.*; import org.springframework.boot.test.json.*; import org.springframework.test.context.junit4.*; import static org.assertj.core.api.Assertions.*; @RunWith(SpringRunner.class) @JsonTest public class MyJsonTests { @Autowired private JacksonTester<VehicleDetails> json; @Test public void testSerialize() throws Exception { VehicleDetails details = new VehicleDetails("Honda", "Civic"); // Assert against a `.json` file in the same package as the test assertThat(this.json.write(details)).isEqualToJson("expected.json"); // Or use JSON path based assertions assertThat(this.json.write(details)).hasJsonPathStringValue("@.make"); assertThat(this.json.write(details)).extractingJsonPathStringValue("@.make") .isEqualTo("Honda"); } @Test public void testDeserialize() throws Exception { String content = "{\"make\":\"Ford\",\"model\":\"Focus\"}"; assertThat(this.json.parse(content)) .isEqualTo(new VehicleDetails("Ford", "Focus")); assertThat(this.json.parseObject(content).getMake()).isEqualTo("Ford"); } }
Note | |
---|---|
JSON helper classes can also be used directly in standard unit tests. Simply
call the |
A list of the auto-configuration that is enabled by @JsonTest
can be
found in the appendix.
To test Spring MVC controllers are working as expected you can use the @WebMvcTest
annotation. @WebMvcTest
will auto-configure the Spring MVC infrastructure and limit
scanned beans to @Controller
, @ControllerAdvice
, @JsonComponent
, Filter
,
WebMvcConfigurer
and HandlerMethodArgumentResolver
. Regular @Component
beans
will not be scanned when using this annotation.
Often @WebMvcTest
will be limited to a single controller and used in combination with
@MockBean
to provide mock implementations for required collaborators.
@WebMvcTest
also auto-configures MockMvc
. Mock MVC offers a powerful way to quickly
test MVC controllers without needing to start a full HTTP server.
Tip | |
---|---|
You can also auto-configure |
import org.junit.*; import org.junit.runner.*; import org.springframework.beans.factory.annotation.*; import org.springframework.boot.test.autoconfigure.web.servlet.*; import org.springframework.boot.test.mock.mockito.*; import static org.assertj.core.api.Assertions.*; import static org.mockito.BDDMockito.*; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; @RunWith(SpringRunner.class) @WebMvcTest(UserVehicleController.class) public class MyControllerTests { @Autowired private MockMvc mvc; @MockBean private UserVehicleService userVehicleService; @Test public void testExample() throws Exception { given(this.userVehicleService.getVehicleDetails("sboot")) .willReturn(new VehicleDetails("Honda", "Civic")); this.mvc.perform(get("/sboot/vehicle").accept(MediaType.TEXT_PLAIN)) .andExpect(status().isOk()).andExpect(content().string("Honda Civic")); } }
Tip | |
---|---|
If you need to configure elements of the auto-configuration (for example when servlet
filters should be applied) you can use attributes in the |
If you use HtmlUnit or Selenium, auto-configuration will also provide an HTMLUnit WebClient
bean
and/or a WebDriver
bean. Here is an example that uses HtmlUnit:
import com.gargoylesoftware.htmlunit.*; import org.junit.*; import org.junit.runner.*; import org.springframework.beans.factory.annotation.*; import org.springframework.boot.test.autoconfigure.web.servlet.*; import org.springframework.boot.test.mock.mockito.*; import static org.assertj.core.api.Assertions.*; import static org.mockito.BDDMockito.*; @RunWith(SpringRunner.class) @WebMvcTest(UserVehicleController.class) public class MyHtmlUnitTests { @Autowired private WebClient webClient; @MockBean private UserVehicleService userVehicleService; @Test public void testExample() throws Exception { given(this.userVehicleService.getVehicleDetails("sboot")) .willReturn(new VehicleDetails("Honda", "Civic")); HtmlPage page = this.webClient.getPage("/sboot/vehicle.html"); assertThat(page.getBody().getTextContent()).isEqualTo("Honda Civic"); } }
Note | |
---|---|
By default Spring Boot will put |
A list of the auto-configuration that is enabled by @WebMvcTest
can be
found in the appendix.
To test Spring WebFlux controllers are working as expected you can use the @WebFluxTest
annotation. @WebFluxTest
will auto-configure the Spring WebFlux infrastructure and limit
scanned beans to @Controller
, @ControllerAdvice
, @JsonComponent
,and
WebFluxConfigurer
. Regular @Component
beans will not be scanned when using this
annotation.
Often @WebFluxTest
will be limited to a single controller and used in combination with
@MockBean
to provide mock implementations for required collaborators.
@WebFluxTest
also auto-configures WebTestClient
, which offers a powerful way to quickly
test WebFlux controllers without needing to start a full HTTP server.
Tip | |
---|---|
You can also auto-configure |
import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest; import org.springframework.http.MediaType; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.web.reactive.server.WebTestClient; @RunWith(SpringRunner.class) @WebFluxTest(UserVehicleController.class) public class MyControllerTests { @Autowired private WebTestClient webClient; @MockBean private UserVehicleService userVehicleService; @Test public void testExample() throws Exception { given(this.userVehicleService.getVehicleDetails("sboot")) .willReturn(new VehicleDetails("Honda", "Civic")); this.webClient.get().uri("/sboot/vehicle").accept(MediaType.TEXT_PLAIN) .exchange() .expectStatus().isOk() .expectBody(String.class).isEqualTo("Honda Civic"); } }
A list of the auto-configuration that is enabled by @WebFluxTest
can be
found in the appendix.
@DataJpaTest
can be used if you want to test JPA applications. By default it will
configure an in-memory embedded database, scan for @Entity
classes and configure Spring
Data JPA repositories. Regular @Component
beans will not be loaded into the
ApplicationContext
.
Data JPA tests are transactional and rollback at the end of each test by default, see the relevant section in the Spring Reference Documentation for more details. If that’s not what you want, you can disable transaction management for a test or for the whole class as follows:
import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; @RunWith(SpringRunner.class) @DataJpaTest @Transactional(propagation = Propagation.NOT_SUPPORTED) public class ExampleNonTransactionalTests { }
Data JPA tests may also inject a
TestEntityManager
bean which provides an alternative to the standard JPA EntityManager
specifically
designed for tests. If you want to use TestEntityManager
outside of @DataJpaTests
you
can also use the @AutoConfigureTestEntityManager
annotation. A JdbcTemplate
is also
available if you need that.
import org.junit.*; import org.junit.runner.*; import org.springframework.boot.test.autoconfigure.orm.jpa.*; import static org.assertj.core.api.Assertions.*; @RunWith(SpringRunner.class) @DataJpaTest public class ExampleRepositoryTests { @Autowired private TestEntityManager entityManager; @Autowired private UserRepository repository; @Test public void testExample() throws Exception { this.entityManager.persist(new User("sboot", "1234")); User user = this.repository.findByUsername("sboot"); assertThat(user.getUsername()).isEqualTo("sboot"); assertThat(user.getVin()).isEqualTo("1234"); } }
In-memory embedded databases generally work well for tests since they are fast and don’t
require any developer installation. If, however, you prefer to run tests against a real
database you can use the @AutoConfigureTestDatabase
annotation:
@RunWith(SpringRunner.class) @DataJpaTest @AutoConfigureTestDatabase(replace=Replace.NONE) public class ExampleRepositoryTests { // ... }
A list of the auto-configuration that is enabled by @DataJpaTest
can be
found in the appendix.
@JdbcTest
is similar to @DataJpaTest
but for pure jdbc-related tests. By default it
will also configure an in-memory embedded database and a JdbcTemplate
. Regular
@Component
beans will not be loaded into the ApplicationContext
.
JDBC tests are transactional and rollback at the end of each test by default, see the relevant section in the Spring Reference Documentation for more details. If that’s not what you want, you can disable transaction management for a test or for the whole class as follows:
import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.autoconfigure.jdbc.JdbcTest; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; @RunWith(SpringRunner.class) @JdbcTest @Transactional(propagation = Propagation.NOT_SUPPORTED) public class ExampleNonTransactionalTests { }
If you prefer your test to run against a real database, you can use the
@AutoConfigureTestDatabase
annotation the same way as for DataJpaTest
.
A list of the auto-configuration that is enabled by @JdbcTest
can be
found in the appendix.
@JooqTest
can be used in a similar fashion as @JdbcTest
but for jOOQ related tests. As
jOOQ relies heavily on a Java-based schema that corresponds with the database schema, the
existing DataSource
will be used. If you want to replace it by an in-memory database you
can use @AutoconfigureTestDatabase
to override those settings.
@JooqTest
will configure a DSLContext
. Regular @Component
beans will not be loaded
into the ApplicationContext
:
import org.jooq.DSLContext; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.autoconfigure.jooq.JooqTest; import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @JooqTest public class ExampleJooqTests { @Autowired private DSLContext dslContext; }
JOOQ tests are transactional and rollback at the end of each test by default. If that’s not what you want, you can disable transaction management for a test or for the whole test class as shown in the example above.
A list of the auto-configuration that is enabled by @JooqTest
can be
found in the appendix.
@DataMongoTest
can be used if you want to test MongoDB applications. By default, it will
configure an in-memory embedded MongoDB (if available), configure a MongoTemplate
, scan
for @Document
classes and configure Spring Data MongoDB repositories. Regular
@Component
beans will not be loaded into the ApplicationContext
:
import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.data.mongo.DataMongoTest; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @DataMongoTest public class ExampleDataMongoTests { @Autowired private MongoTemplate mongoTemplate; // }
In-memory embedded MongoDB generally works well for tests since it is fast and doesn’t require any developer installation. If, however, you prefer to run tests against a real MongoDB server you should exclude the embedded MongoDB auto-configuration:
import org.junit.runner.RunWith; import org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration; import org.springframework.boot.test.autoconfigure.data.mongo.DataMongoTest; import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @DataMongoTest(excludeAutoConfiguration = EmbeddedMongoAutoConfiguration.class) public class ExampleDataMongoNonEmbeddedTests { }
A list of the auto-configuration that is enabled by @DataMongoTest
can be
found in the appendix.
@DataNeo4jTest
can be used if you want to test Neo4j applications. By default, it will
use an in-memory embedded Neo4j (if the embedded driver is available), scan for
@NodeEntity
classes and configure Spring Data Neo4j repositories. Regular @Component
beans will not be loaded into the ApplicationContext
:
import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.data.neo4j.DataNeo4jTest; import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @DataNeo4jTest public class ExampleDataNeo4jTests { @Autowired private YourRepository repository; // }
Data Neo4j tests are transactional and rollback at the end of each test by default, see the relevant section in the Spring Reference Documentation for more details. If that’s not what you want, you can disable transaction management for a test or for the whole class as follows:
import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.autoconfigure.data.neo4j.DataNeo4jTest; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; @RunWith(SpringRunner.class) @DataNeo4jTest @Transactional(propagation = Propagation.NOT_SUPPORTED) public class ExampleNonTransactionalTests { }
A list of the auto-configuration that is enabled by @DataNeo4jTest
can be
found in the appendix.
@DataRedisTest
can be used if you want to test Redis applications. By default, it will
scan for @RedisHash
classes and configure Spring Data Redis repositories. Regular
@Component
beans will not be loaded into the ApplicationContext
:
import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.data.redis.DataRedisTest; import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @DataRedisTest public class ExampleDataRedisTests { @Autowired private YourRepository repository; // }
A list of the auto-configuration that is enabled by @DataRedisTest
can be
found in the appendix.
@DataLdapTest
can be used if you want to test LDAP applications. By default, it will
configure an in-memory embedded LDAP (if available), a LdapTemplate
, scan for @Entry
classes and configure Spring Data LDAP repositories. Regular @Component
beans will not
be loaded into the ApplicationContext
:
import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.data.ldap.DataLdapTest; import org.springframework.ldap.core.LdapTemplate; import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @DataLdapTest public class ExampleDataLdapTests { @Autowired private LdapTemplate ldapTemplate; // }
In-memory embedded LDAP generally works well for tests since it is fast and doesn’t require any developer installation. If, however, you prefer to run tests against a real LDAP server you should exclude the embedded LDAP auto-configuration:
import org.junit.runner.RunWith; import org.springframework.boot.autoconfigure.ldap.embedded.EmbeddedLdapAutoConfiguration; import org.springframework.boot.test.autoconfigure.data.ldap.DataLdapTest; import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @DataLdapTest(excludeAutoConfiguration = EmbeddedLdapAutoConfiguration.class) public class ExampleDataLdapNonEmbeddedTests { }
A list of the auto-configuration that is enabled by @DataLdapTest
can be
found in the appendix.
The @RestClientTest
annotation can be used if you want to test REST clients. By default
it will auto-configure Jackson, GSON and Jsonb support, configure a RestTemplateBuilder
and add support for MockRestServiceServer
. The specific beans that you want to test
should be specified using value
or components
attribute of @RestClientTest
:
@RunWith(SpringRunner.class) @RestClientTest(RemoteVehicleDetailsService.class) public class ExampleRestClientTest { @Autowired private RemoteVehicleDetailsService service; @Autowired private MockRestServiceServer server; @Test public void getVehicleDetailsWhenResultIsSuccessShouldReturnDetails() throws Exception { this.server.expect(requestTo("/greet/details")) .andRespond(withSuccess("hello", MediaType.TEXT_PLAIN)); String greeting = this.service.callRestService(); assertThat(greeting).isEqualTo("hello"); } }
A list of the auto-configuration that is enabled by @RestClientTest
can be
found in the appendix.
The @AutoConfigureRestDocs
annotation can be used if you want to use Spring REST Docs
in your tests with Mock MVC or REST Assured. It removes the need for Spring REST Docs'
JUnit rule.
@AutoConfigureRestDocs
can be used to override the default output directory
(target/generated-snippets
if you are using Maven or build/generated-snippets
if you
are using Gradle). It can also be used to configure the host, scheme, and port that will
appear in any documented URIs.
@AutoConfigureRestDocs
customizes the MockMvc
bean to use Spring REST Docs, Inject it
using @Autowired
and use it in your tests as you normally would when using Mock MVC and
Spring REST Docs:
import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.http.MediaType; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.web.servlet.MockMvc; import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; @RunWith(SpringRunner.class) @WebMvcTest(UserController.class) @AutoConfigureRestDocs public class UserDocumentationTests { @Autowired private MockMvc mvc; @Test public void listUsers() throws Exception { this.mvc.perform(get("/users").accept(MediaType.TEXT_PLAIN)) .andExpect(status().isOk()) .andDo(document("list-users")); } }
If you require more control over Spring REST Docs' configuration than offered by the
attributes of @AutoConfigureRestDocs
, a RestDocsMockMvcConfigurationCustomizer
bean
can be used:
@TestConfiguration static class CustomizationConfiguration implements RestDocsMockMvcConfigurationCustomizer { @Override public void customize(MockMvcRestDocumentationConfigurer configurer) { configurer.snippets().withTemplateFormat(TemplateFormats.markdown()); } }
If you want to make use of Spring REST Docs' support for a parameterized output directory,
you can create a RestDocumentationResultHandler
bean. The auto-configuration will
call alwaysDo
with this result handler, thereby causing each MockMvc
call to
automatically generate the default snippets:
@TestConfiguration static class ResultHandlerConfiguration { @Bean public RestDocumentationResultHandler restDocumentation() { return MockMvcRestDocumentation.document("{method-name}"); } }
@AutoConfigureRestDocs
makes a RequestSpecification
bean, preconfigured to use Spring REST
Docs, available to your tests. Inject it using @Autowired
and use it in your tests as you
normally would when using REST Assured and Spring REST Docs:
import io.restassured.specification.RequestSpecification; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.boot.web.server.LocalServerPort; import org.springframework.test.context.junit4.SpringRunner; import static io.restassured.RestAssured.given; import static org.hamcrest.CoreMatchers.is; import static org.springframework.restdocs.restassured3.RestAssuredRestDocumentation.document; @RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) @AutoConfigureRestDocs public class UserDocumentationTests { @LocalServerPort private int port; @Autowired private RequestSpecification documentationSpec; @Test public void listUsers() throws Exception { given(this.documentationSpec).filter(document("list-users")).when() .port(this.port).get("/").then().assertThat().statusCode(is(200)); } }
If you require more control over Spring REST Docs' configuration than offered by the
attributes of @AutoConfigureRestDocs
, a RestDocsRestAssuredConfigurationCustomizer
bean can be used:
@TestConfiguration public static class CustomizationConfiguration implements RestDocsRestAssuredConfigurationCustomizer { @Override public void customize(RestAssuredRestDocumentationConfigurer configurer) { configurer.snippets().withTemplateFormat(TemplateFormats.markdown()); } }
If you wish to use Spock to test a Spring Boot application you should add a dependency
on Spock’s spock-spring
module to your application’s build. spock-spring
integrates
Spring’s test framework into Spock. It is recommended that you use Spock 1.1 or later to
benefit from a number of recent improvements to Spock’s Spring Framework and Spring Boot
integration. Please refer to the
documentation for Spock’s Spring module for further details.
A few test utility classes are packaged as part of spring-boot
that are generally
useful when testing your application.
ConfigFileApplicationContextInitializer
is an ApplicationContextInitializer
that
can apply to your tests to load Spring Boot application.properties
files. You can use
this when you don’t need the full features provided by @SpringBootTest
.
@ContextConfiguration(classes = Config.class, initializers = ConfigFileApplicationContextInitializer.class)
Note | |
---|---|
Using |
EnvironmentTestUtils
allows you to quickly add properties to a
ConfigurableEnvironment
or ConfigurableApplicationContext
. Simply call it with
key=value
strings:
EnvironmentTestUtils.addEnvironment(env, "org=Spring", "name=Boot");
OutputCapture
is a JUnit Rule
that you can use to capture System.out
and
System.err
output. Simply declare the capture as a @Rule
then use toString()
for assertions:
import org.junit.Rule; import org.junit.Test; import org.springframework.boot.test.rule.OutputCapture; import static org.hamcrest.Matchers.*; import static org.junit.Assert.*; public class MyTest { @Rule public OutputCapture capture = new OutputCapture(); @Test public void testName() throws Exception { System.out.println("Hello World!"); assertThat(capture.toString(), containsString("World")); } }
TestRestTemplate
is a convenience alternative to Spring’s RestTemplate
that is useful
in integration tests. You can get a vanilla template or one that sends Basic HTTP
authentication (with a username and password). In either case the template will behave
in a test-friendly way by not throwing exceptions on server-side errors. It is
recommended, but not mandatory, to use Apache HTTP Client (version 4.3.2 or better), and
if you have that on your classpath the TestRestTemplate
will respond by configuring
the client appropriately. If you do use Apache’s HTTP client some additional test-friendly
features will be enabled:
TestRestTemplate
can be instantiated directly in your integration tests:
public class MyTest { private TestRestTemplate template = new TestRestTemplate(); @Test public void testRequest() throws Exception { HttpHeaders headers = template.getForEntity("http://myhost.com/example", String.class).getHeaders(); assertThat(headers.getLocation().toString(), containsString("myotherhost")); } }
Alternatively, if you are using the @SpringBootTest
annotation with
WebEnvironment.RANDOM_PORT
or WebEnvironment.DEFINED_PORT
, you can just inject a
fully configured TestRestTemplate
and start using it. If necessary, additional
customizations can be applied via the RestTemplateBuilder
bean. Any URLs that do not
specify a host and port will automatically connect to the embedded server:
@RunWith(SpringRunner.class) @SpringBootTest public class MyTest { @Autowired private TestRestTemplate template; @Test public void testRequest() throws Exception { HttpHeaders headers = template.getForEntity("/example", String.class).getHeaders(); assertThat(headers.getLocation().toString(), containsString("myotherhost")); } @TestConfiguration static class Config { @Bean public RestTemplateBuilder restTemplateBuilder() { return new RestTemplateBuilder() .additionalMessageConverters(...) .customizers(...); } } }