Spring Boot provides a number of useful tools for testing your application. The
spring-boot-starter-test POM provides Spring Test, JUnit, Hamcrest and Mockito
dependencies. There are also useful test utilities in the core spring-boot module under
the org.springframework.boot.test package.
If you use the
spring-boot-starter-test ‘Starter POM’ (in the test scope), you will find
the following provided libraries:
assertThat style JUnit assertions.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 POM’ 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 @SpringApplicationConfiguration annotation as an alternative
to the standard spring-test @ContextConfiguration annotation. If you use
@SpringApplicationConfiguration to configure the ApplicationContext used in your
tests, it will be created via SpringApplication and you will get the additional Spring
Boot features.
For example:
@RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = SampleDataJpaApplication.class) public class CityRepositoryIntegrationTests { @Autowired CityRepository repository; // ... }
![]() | Tip |
|---|---|
The context loader guesses whether you want to test a web application or not (e.g.
with |
If you want a web application to start up and listen on its normal port, so you can test
it with HTTP (e.g. using RestTemplate), annotate your test class (or one of its
superclasses) with @WebIntegrationTest. This can be very useful because it means you can
test the full stack of your application, but also inject its components into the test
class and use them to assert the internal state of the application after an HTTP
interaction. For example:
@RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = SampleDataJpaApplication.class) @WebIntegrationTest public class CityRepositoryIntegrationTests { @Autowired CityRepository repository; RestTemplate restTemplate = new TestRestTemplate(); // ... interact with the running server }
![]() | Note |
|---|---|
Spring’s test framework will cache application contexts between tests. Therefore, as long as your tests share the same configuration, the time consuming process of starting and stopping the server will only happen once, regardless of the number of tests that actually run. |
To change the port you can add environment properties to @WebIntegrationTest as colon-
or equals-separated name-value pairs, e.g. @WebIntegrationTest("server.port:9000").
Additionally you can set the server.port and management.port properties to 0
in order to run your integration tests using random ports. For example:
@RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = MyApplication.class) @WebIntegrationTest({"server.port=0", "management.port=0"}) public class SomeIntegrationTests { // ... }
See Section 64.5, “Discover the HTTP port at runtime” for a description of how you can discover the actual port that was allocated for the duration of the tests.
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.
Please note that you cannot use the @SpringApplicationConfiguration annotation that was
described above as Spock
does not find the
@ContextConfiguration meta-annotation. To work around this limitation, you should use
the @ContextConfiguration annotation directly and configure it to use the Spring
Boot specific context loader:
@ContextConfiguration(loader = SpringApplicationContextLoader.class) class ExampleSpec extends Specification { // ... }
![]() | Note |
|---|---|
The annotations described above
can be used with Spock, i.e. you can annotate your |
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 @SpringApplicationConfiguration.
@ContextConfiguration(classes = Config.class, initializers = ConfigFileApplicationContextInitializer.class)
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.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 subclass of 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: not following redirects (so you can assert the response location),
ignoring cookies (so the template is stateless), and 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.
public class MyTest { RestTemplate template = new TestRestTemplate(); @Test public void testRequest() throws Exception { HttpHeaders headers = template.getForEntity("http://myhost.com", String.class).getHeaders(); assertThat(headers.getLocation().toString(), containsString("myotherhost")); } }