|
|
|
@ -4161,10 +4161,13 @@ class for more details.
|
|
|
|
|
|
|
|
|
|
[[boot-features-testing]]
|
|
|
|
|
== Testing
|
|
|
|
|
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.
|
|
|
|
|
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 the `spring-boot-starter-test` '`Starter POM`' which
|
|
|
|
|
imports both Spring Boot test modules as well has JUnit, AssertJ, Hamcrest and a number
|
|
|
|
|
of other useful libraries.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -4174,16 +4177,21 @@ If you use the
|
|
|
|
|
`spring-boot-starter-test` '`Starter POM`' (in the `test` `scope`), you will find
|
|
|
|
|
the following provided libraries:
|
|
|
|
|
|
|
|
|
|
* Spring Test -- integration test support for Spring applications.
|
|
|
|
|
* JUnit -- The de-facto standard for unit testing Java applications.
|
|
|
|
|
* Hamcrest -- A library of matcher objects (also known as constraints or predicates)
|
|
|
|
|
allowing `assertThat` style JUnit assertions.
|
|
|
|
|
* Mockito -- A Java mocking framework.
|
|
|
|
|
* http://junit.org[JUnit] -- The de-facto standard for unit testing Java applications.
|
|
|
|
|
* {spring-reference}/#integration-testing.html[Spring Test] & Spring Boot Test -- utilties and integration test support for Spring Boot
|
|
|
|
|
applications.
|
|
|
|
|
* http://joel-costigliola.github.io/assertj/[AssertJ] - A fluent assertion library.
|
|
|
|
|
* http://hamcrest.org/JavaHamcrest/[Hamcrest] -- A library of matcher objects (also known
|
|
|
|
|
as constraints or predicates).
|
|
|
|
|
* http://mockito.org/[Mockito] -- A Java mocking framework.
|
|
|
|
|
* https://github.com/skyscreamer/JSONassert[JSONassert] -- An assertion library for JSON.
|
|
|
|
|
* https://github.com/jayway/JsonPath[JsonPath] -- XPath for JSON.
|
|
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[[boot-features-testing-spring-applications]]
|
|
|
|
|
=== Testing Spring applications
|
|
|
|
|
One of the major advantages of dependency injection is that it should make your code
|
|
|
|
@ -4207,100 +4215,484 @@ documentation.
|
|
|
|
|
|
|
|
|
|
[[boot-features-testing-spring-boot-applications]]
|
|
|
|
|
=== Testing Spring Boot applications
|
|
|
|
|
A Spring Boot application is just a Spring `ApplicationContext` so nothing very special
|
|
|
|
|
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.
|
|
|
|
|
Spring Boot provides three annotations which can be used as an alternative the standard
|
|
|
|
|
`spring-test` `@ContextConfiguration` annotation when you need Spring Boot features. All
|
|
|
|
|
three work by creating the `ApplicationContext` used in your tests via
|
|
|
|
|
`SpringApplication`.
|
|
|
|
|
|
|
|
|
|
For example:
|
|
|
|
|
[source,java,indent=0,subs="verbatim,quotes,attributes"]
|
|
|
|
|
The specific annotation that you choose will depend on the type of test that you are writing:
|
|
|
|
|
|
|
|
|
|
* `@SpringApplicationTest` -- Loads an `ApplicationContext` or `WebApplicationContext`
|
|
|
|
|
(depending on your classpath) using `SpringApplication` and provides a mock servlet environment. Embedded servlet containers are not started
|
|
|
|
|
when using this annotation.
|
|
|
|
|
* `@WebIntegrationTest` -- Loads an `EmbeddedWebApplicationContext` using
|
|
|
|
|
`SpringApplication` and provides a real servlet environment. Embedded servlet containers
|
|
|
|
|
are started and listening on a defined or random port.
|
|
|
|
|
* `@IntegrationTest` -- Loads an `ApplicationContext` using `SpringApplication` but does
|
|
|
|
|
not provides _any_ servlet environment (mock or otherwise).
|
|
|
|
|
|
|
|
|
|
NOTE: In addition to `@SpringApplicationTest`, `@WebIntegrationTest` and
|
|
|
|
|
`@IntegrationTest` a number of other annotations are also provided for testing more
|
|
|
|
|
specific slices of an application. See below for details.
|
|
|
|
|
|
|
|
|
|
TIP: Don't forget to also add `@RunWith(SpringRunner.class)` to your test, otherwise
|
|
|
|
|
the annotations will be ignored.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[[boot-features-testing-spring-boot-applications-detecting-config]]
|
|
|
|
|
==== Detecting configuration
|
|
|
|
|
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 defined 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
|
|
|
|
|
<<using-boot-structuring-your-code, structure your code>> in a sensible way your main
|
|
|
|
|
configuration is usually found.
|
|
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[[boot-features-testing-spring-boot-applications-excluding-config]]
|
|
|
|
|
==== Excluding test configuration
|
|
|
|
|
If your application uses component scanning, for example if you use
|
|
|
|
|
`@SpringBootApplication` or `@ComponentScan`, you may find components or configurations
|
|
|
|
|
created only for specific tests accidentally get picked up everywhere.
|
|
|
|
|
|
|
|
|
|
To help prevent this, Spring Boot provides `@TestComponent` and `@TestConfiguration`
|
|
|
|
|
annotations that can be used on classes in `src/test/java` to indicate that they should
|
|
|
|
|
not be picked up by scanning.
|
|
|
|
|
|
|
|
|
|
NOTE: `@TestComponent` and `@TestConfiguration` are only needed on top level classes. If
|
|
|
|
|
you define `@Configuration` or `@Component` as inner-classes within a test, they will be
|
|
|
|
|
automatically filtered.
|
|
|
|
|
|
|
|
|
|
NOTE: If you directly use `@ComponentScan` (i.e. not via `@SpringBootApplication`) you
|
|
|
|
|
will need to register the `TypeExcludeFilter` with it. See
|
|
|
|
|
{dc-spring-boot}/context/TypeExcludeFilter.{dc-ext}[the Javadoc] for details.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[[boot-features-testing-spring-boot-applications-using-springapplicationtest]]
|
|
|
|
|
==== Using @SpringApplicationTest
|
|
|
|
|
Use the `@SpringApplicationTest` annotation to load a `ApplicationContext` or
|
|
|
|
|
`WebApplicationContext` via `SpringApplication` and configure it with a mock
|
|
|
|
|
servlet environment. Embedded servlet containers will not be started when using
|
|
|
|
|
`@SpringApplicationTest`.
|
|
|
|
|
|
|
|
|
|
A `WebApplicationContext` is created when Servlet API jars are present on your
|
|
|
|
|
classpath. If you're developing a non-web application, the regular
|
|
|
|
|
`ApplicationContext` is used.
|
|
|
|
|
|
|
|
|
|
The `@Configuration` classes to load can either be explicitly defined using
|
|
|
|
|
`@ContextConfiguration`, specified as inner-classes or
|
|
|
|
|
<<boot-features-testing-spring-boot-applications-detecting-config, detected automatically>>
|
|
|
|
|
|
|
|
|
|
[source,java,indent=0]
|
|
|
|
|
----
|
|
|
|
|
@RunWith(SpringJUnit4ClassRunner.class)
|
|
|
|
|
@SpringApplicationConfiguration(SampleDataJpaApplication.class)
|
|
|
|
|
public class CityRepositoryIntegrationTests {
|
|
|
|
|
import org.junit.*;
|
|
|
|
|
import org.junit.runner.*;
|
|
|
|
|
import org.springframework.beans.factory.annotation.*;
|
|
|
|
|
import org.springframework.boot.test.context.*;
|
|
|
|
|
import org.springframework.test.context.junit4.*;
|
|
|
|
|
|
|
|
|
|
@RunWith(SpringRunner.class)
|
|
|
|
|
@SpringApplicationTest
|
|
|
|
|
public class MySpringApplicationTests {
|
|
|
|
|
|
|
|
|
|
@Autowired
|
|
|
|
|
CityRepository repository;
|
|
|
|
|
private MyComponent component;
|
|
|
|
|
|
|
|
|
|
// ...
|
|
|
|
|
// ... tests
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
----
|
|
|
|
|
|
|
|
|
|
TIP: The context loader guesses whether you want to test a web application or not (e.g.
|
|
|
|
|
with `MockMvc`) by looking for the `@WebIntegrationTest` or `@WebAppConfiguration`
|
|
|
|
|
annotations. (`MockMvc` and `@WebAppConfiguration` are part of `spring-test`).
|
|
|
|
|
|
|
|
|
|
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:
|
|
|
|
|
|
|
|
|
|
[source,java,indent=0,subs="verbatim,quotes,attributes"]
|
|
|
|
|
[[boot-features-testing-spring-boot-applications-using-webintegrationtest]]
|
|
|
|
|
==== Using @WebIntegrationTest
|
|
|
|
|
Use the `@WebIntegrationTest` annotation to load a `WebApplicationContext` via
|
|
|
|
|
`SpringApplication` and configure it with fully running server listening on the appropriate
|
|
|
|
|
port.
|
|
|
|
|
|
|
|
|
|
The `@Configuration` classes to load can either be explicitly defined using
|
|
|
|
|
`@ContextConfiguration`, specified as inner-classes or
|
|
|
|
|
<<boot-features-testing-spring-boot-applications-detecting-config, detected automatically>>
|
|
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
|
|
|
|
|
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`
|
|
|
|
|
or use the `randomPort` attribute in order to run your integration tests using
|
|
|
|
|
random ports.
|
|
|
|
|
|
|
|
|
|
[source,java,indent=0]
|
|
|
|
|
----
|
|
|
|
|
@RunWith(SpringJUnit4ClassRunner.class)
|
|
|
|
|
@SpringApplicationConfiguration(SampleDataJpaApplication.class)
|
|
|
|
|
@WebIntegrationTest
|
|
|
|
|
public class CityRepositoryIntegrationTests {
|
|
|
|
|
import org.junit.*;
|
|
|
|
|
import org.junit.runner.*;
|
|
|
|
|
import org.springframework.boot.test.context.web.*;
|
|
|
|
|
import org.springframework.boot.test.web.client.*;
|
|
|
|
|
import org.springframework.test.context.junit4.*;
|
|
|
|
|
|
|
|
|
|
import static org.assertj.core.api.Assertions.*
|
|
|
|
|
|
|
|
|
|
@RunWith(SpringRunner.class)
|
|
|
|
|
@WebIntegrationTest(randomPort=true)
|
|
|
|
|
public class MyWebIntegrationTests {
|
|
|
|
|
|
|
|
|
|
@Autowired
|
|
|
|
|
CityRepository repository;
|
|
|
|
|
private TestRestTemplate restTemplate;
|
|
|
|
|
|
|
|
|
|
RestTemplate restTemplate = new TestRestTemplate();
|
|
|
|
|
@Test
|
|
|
|
|
public void exampleTest() {
|
|
|
|
|
String body = this.restTemplate.getForObject("/", String.class);
|
|
|
|
|
assertThat(body).isEqualTo("Hello World");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
----
|
|
|
|
|
|
|
|
|
|
// ... interact with the running server
|
|
|
|
|
See <<howto-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're not using the
|
|
|
|
|
injected `TestRestTemplate`.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[[boot-features-testing-spring-boot-applications-using-integrationtest]]
|
|
|
|
|
==== Using @IntegrationTest
|
|
|
|
|
Use the `@IntegrationTest` annotation to load an `ApplicationContext` via
|
|
|
|
|
`SpringApplication` for non web-applications. Mock servlet support is explicitly disabled
|
|
|
|
|
for tests annotated with `@IntegrationTest`.
|
|
|
|
|
|
|
|
|
|
The `@Configuration` classes to load can either be explicitly defined using
|
|
|
|
|
`@ContextConfiguration`, specified as inner-classes or
|
|
|
|
|
<<boot-features-testing-spring-boot-applications-detecting-config, detected automatically>>
|
|
|
|
|
|
|
|
|
|
[source,java,indent=0]
|
|
|
|
|
----
|
|
|
|
|
import org.junit.*;
|
|
|
|
|
import org.junit.runner.*;
|
|
|
|
|
import org.springframework.beans.factory.annotation.*;
|
|
|
|
|
import org.springframework.boot.test.context.*;
|
|
|
|
|
import org.springframework.test.context.junit4.*;
|
|
|
|
|
|
|
|
|
|
@RunWith(SpringRunner.class)
|
|
|
|
|
@IntegrationTest
|
|
|
|
|
public class MyIntegrationTests {
|
|
|
|
|
|
|
|
|
|
@Autowired
|
|
|
|
|
private MyComponent component;
|
|
|
|
|
|
|
|
|
|
// ... tests
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
----
|
|
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
NOTE: Although it's possible to use the `@WebAppConfiguration` annotation in combination
|
|
|
|
|
with `@IntegrationTest` if you want to start a full web server, the `@WebIntegrationTest`
|
|
|
|
|
annotation is generally preferable.
|
|
|
|
|
|
|
|
|
|
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:
|
|
|
|
|
|
|
|
|
|
[source,java,indent=0,subs="verbatim,quotes,attributes"]
|
|
|
|
|
|
|
|
|
|
[[boot-features-testing-spring-boot-applications-mocking-beans]]
|
|
|
|
|
==== Mocking Beans
|
|
|
|
|
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.
|
|
|
|
|
|
|
|
|
|
Here's a typical example where we replace an existing `RemoteService` bean with a mock
|
|
|
|
|
implementation:
|
|
|
|
|
|
|
|
|
|
[source,java,indent=0]
|
|
|
|
|
----
|
|
|
|
|
@RunWith(SpringJUnit4ClassRunner.class)
|
|
|
|
|
@SpringApplicationConfiguration(MyApplication.class)
|
|
|
|
|
@WebIntegrationTest({"server.port=0", "management.port=0"})
|
|
|
|
|
public class SomeIntegrationTests {
|
|
|
|
|
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)
|
|
|
|
|
@SpringApplicationTest
|
|
|
|
|
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");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
----
|
|
|
|
|
|
|
|
|
|
Alternatively, you can use the `randomPort` convenience attribute to set `server.port=0`.
|
|
|
|
|
For example:
|
|
|
|
|
|
|
|
|
|
[source,java,indent=0,subs="verbatim,quotes,attributes"]
|
|
|
|
|
|
|
|
|
|
[[boot-features-testing-spring-boot-applications-testing-autoconfigured-tests]]
|
|
|
|
|
==== Auto-configured tests
|
|
|
|
|
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 and database calls in those tests; or you _might be wanting_ to test JPA
|
|
|
|
|
entites, 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 work 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.
|
|
|
|
|
|
|
|
|
|
TIP: It's also possible to use the `@AutoConfigure...` annotations with the standard
|
|
|
|
|
`@SpringApplicationTest` annotation. You can use this combination if you're not interested
|
|
|
|
|
in '`slicing`' your application but you want some of the auto-configured test beans.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[[boot-features-testing-spring-boot-applications-testing-autoconfigured-json-tests]]
|
|
|
|
|
==== Auto-configured JSON tests
|
|
|
|
|
To test that Object JSON serilization and deserialization is working as expected you can
|
|
|
|
|
use the `@JsonTest` annotation. `@JsonTest` will auto-configure Jackson ObjectMappers,
|
|
|
|
|
any `@JsonComponent` beans and any Jackson `Modules`. It also configures `Gson`
|
|
|
|
|
if you happen to be using that instead of, or as well as, Jackson. 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 `JacksonHelper`, `GsonHelper` and
|
|
|
|
|
`BasicJsonHelper` classes can be used for Jackson, Gson and Strings respectively. Any
|
|
|
|
|
helper fields on the test class will be automatically initialized when using `@JsonTest`.
|
|
|
|
|
|
|
|
|
|
[source,java,indent=0]
|
|
|
|
|
----
|
|
|
|
|
@RunWith(SpringJUnit4ClassRunner.class)
|
|
|
|
|
@SpringApplicationConfiguration(MyApplication.class)
|
|
|
|
|
@WebIntegrationTest(randomPort = true)
|
|
|
|
|
public class SomeIntegrationTests {
|
|
|
|
|
import org.junit.*;
|
|
|
|
|
import org.junit.runner.*;
|
|
|
|
|
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 {
|
|
|
|
|
|
|
|
|
|
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");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
----
|
|
|
|
|
|
|
|
|
|
See <<howto-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.
|
|
|
|
|
|
|
|
|
|
NOTE: JSON helper classes can also be used directly in standard unit tests. Simply
|
|
|
|
|
call the `initFields` method of the helper in your `@Before` method if you aren't using
|
|
|
|
|
`@JsonTest`.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[[boot-features-testing-spring-boot-applications-testing-autoconfigured-mvc-tests]]
|
|
|
|
|
==== Auto-configured Spring MVC tests
|
|
|
|
|
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` is meta-annotated with `@AutoConfigureMockMvc` which provides
|
|
|
|
|
auto-configuration of `MockMvc`. Mock MVC offers a powerful way to quickly test MVC
|
|
|
|
|
controllers without needing to start a full HTTP server.
|
|
|
|
|
|
|
|
|
|
[source,java,indent=0]
|
|
|
|
|
----
|
|
|
|
|
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 `@AutoConfigureJsonTesters` annotation.
|
|
|
|
|
|
|
|
|
|
If you use HtmlUnit or Selenium, auto-configuration will also provide a `WebClient` bean
|
|
|
|
|
and/or a `WebDriver` bean. Here is an example that uses HtmlUnit:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[source,java,indent=0]
|
|
|
|
|
----
|
|
|
|
|
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");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
----
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[[boot-features-testing-spring-boot-applications-testing-autoconfigured-jpa-test]]
|
|
|
|
|
==== Auto-configured Data JPA tests
|
|
|
|
|
The `@DataJpaTest` can be used if 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 may also inject a
|
|
|
|
|
{sc-spring-boot-test-autoconfigure}/orm/jpa/TestEntityManager.{sc-ext}[`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.
|
|
|
|
|
|
|
|
|
|
[source,java,indent=0]
|
|
|
|
|
----
|
|
|
|
|
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:
|
|
|
|
|
|
|
|
|
|
[source,java,indent=0]
|
|
|
|
|
----
|
|
|
|
|
@RunWith(SpringRunner.class)
|
|
|
|
|
@DataJpaTest
|
|
|
|
|
@AutoConfigureTestDatabase(replace=Replace.NONE)
|
|
|
|
|
public class ExampleRepositoryTests {
|
|
|
|
|
|
|
|
|
|
// ...
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
----
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -4327,7 +4719,7 @@ useful when testing your application.
|
|
|
|
|
==== ConfigFileApplicationContextInitializer
|
|
|
|
|
`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`.
|
|
|
|
|
this when you don't need the full features provided by `@SpringApplicationTest`.
|
|
|
|
|
|
|
|
|
|
[source,java,indent=0]
|
|
|
|
|
----
|
|
|
|
@ -4360,7 +4752,7 @@ for assertions:
|
|
|
|
|
----
|
|
|
|
|
import org.junit.Rule;
|
|
|
|
|
import org.junit.Test;
|
|
|
|
|
import org.springframework.boot.test.OutputCapture;
|
|
|
|
|
import org.springframework.boot.test.rule.OutputCapture;
|
|
|
|
|
|
|
|
|
|
import static org.hamcrest.Matchers.*;
|
|
|
|
|
import static org.junit.Assert.*;
|
|
|
|
@ -4381,7 +4773,6 @@ public class MyTest {
|
|
|
|
|
|
|
|
|
|
[[boot-features-rest-templates-test-utility]]
|
|
|
|
|
==== TestRestTemplate
|
|
|
|
|
|
|
|
|
|
`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
|
|
|
|
|