107 lines
5.5 KiB
Plaintext
107 lines
5.5 KiB
Plaintext
[[howto.testing]]
|
|
== Testing
|
|
Spring Boot includes a number of testing utilities and support classes as well as a dedicated starter that provides common test dependencies.
|
|
This section answers common questions about testing.
|
|
|
|
|
|
|
|
[[howto.testing.with-spring-security]]
|
|
=== Testing With Spring Security
|
|
Spring Security provides support for running tests as a specific user.
|
|
For example, the test in the snippet below will run with an authenticated user that has the `ADMIN` role.
|
|
|
|
include::code:MySecurityTests[]
|
|
|
|
Spring Security provides comprehensive integration with Spring MVC Test and this can also be used when testing controllers using the `@WebMvcTest` slice and `MockMvc`.
|
|
|
|
For additional details on Spring Security's testing support, see Spring Security's {spring-security-docs}/servlet/test/index.html[reference documentation].
|
|
|
|
|
|
|
|
|
|
[[howto.testing.testcontainers]]
|
|
=== Use Testcontainers for Integration Testing
|
|
The https://www.testcontainers.org/[Testcontainers] library provides a way to manage services running inside Docker containers.
|
|
It integrates with JUnit, allowing you to write a test class that can start up a container before any of the tests run.
|
|
Testcontainers is especially useful for writing integration tests that talk to a real backend service such as MySQL, MongoDB, Cassandra and others.
|
|
Testcontainers can be used in a Spring Boot test as follows:
|
|
|
|
include::code:vanilla/MyIntegrationTests[]
|
|
|
|
This will start up a docker container running Neo4j (if Docker is running locally) before any of the tests are run.
|
|
In most cases, you will need to configure the application to connect to the service running in the container.
|
|
|
|
|
|
[[howto.testing.testcontainers.service-connections]]
|
|
==== Service Connections
|
|
A service connection is a connection to any remote service.
|
|
Spring Boot's auto-configuration can consume the details of a service connection and use them to establish a connection to a remote service.
|
|
When doing so, the connection details take precedence over any connection-related configuration properties.
|
|
|
|
When using Testcontainers, connection details can be automatically created for a service running in a container by annotating the container field in the test class.
|
|
|
|
include::code:MyIntegrationTests[]
|
|
|
|
Thanks to `@Neo4jServiceConnection`, the above configuration allows Neo4j-related beans in the application to communicate with Neo4j running inside the Testcontainers-managed Docker container.
|
|
This is done by automatically defining a `Neo4jConnectionDetails` bean which is then used by the Neo4j auto-configuration, overriding any connection-related configuration properties.
|
|
|
|
The following service connection annotations are provided by `spring-boot-test-autoconfigure`:
|
|
|
|
- `@CassandraServiceConnection`
|
|
- `@CouchbaseServiceConnection`
|
|
- `@ElasticsearchServiceConnection`
|
|
- `@InfluxDbServiceConnection`
|
|
- `@JdbcServiceConnection`
|
|
- `@KafkaServiceConnection`
|
|
- `@MongoServiceConnection`
|
|
- `@Neo4jServiceConnection`
|
|
- `@R2dbcServiceConnection`
|
|
- `@RabbitServiceConnection`
|
|
- `@RedisServiceConnection`
|
|
|
|
As with the earlier `@Neo4jConnectionDetails` example, each can be used on a container field. Doing so will automatically configure the application to connect to the service running in the container.
|
|
|
|
|
|
|
|
[[howto.testing.testcontainers.dynamic-properties]]
|
|
==== Dynamic Properties
|
|
A slightly more verbose but also more flexible alternative to service connections is `@DynamicPropertySource`.
|
|
A static `@DynamicPropertySource` method allows adding dynamic property values to the Spring Environment.
|
|
|
|
include::code:/MyIntegrationTests[]
|
|
|
|
The above configuration allows Neo4j-related beans in the application to communicate with Neo4j running inside the Testcontainers-managed Docker container.
|
|
|
|
|
|
|
|
[[howto.testing.slice-tests]]
|
|
=== Structure `@Configuration` classes for inclusion in slice tests
|
|
Slice tests work by restricting Spring Framework's component scanning to a limited set of components based on their type.
|
|
For any beans that are not created through component scanning, for example, beans that are created using the `@Bean` annotation, slice tests will not be able to include/exclude them from the application context.
|
|
Consider this example:
|
|
|
|
[source,java,indent=0,subs="verbatim"]
|
|
----
|
|
include::{docs-java}/howto/testing/slicetests/MyConfiguration.java[]
|
|
----
|
|
|
|
For a `@WebMvcTest` for an application with the above `@Configuration` class, you might expect to have the `SecurityFilterChain` bean in the application context so that you can test if your controller endpoints are secured properly.
|
|
However, `MyConfiguration` is not picked up by @WebMvcTest's component scanning filter because it doesn't match any of the types specified by the filter.
|
|
You can include the configuration explicitly by annotating the test class with `@Import(MyConfiguration.class)`.
|
|
This will load all the beans in `MyConfiguration` including the `BasicDataSource` bean which isn't required when testing the web tier.
|
|
Splitting the configuration class into two will enable importing just the security configuration.
|
|
|
|
[source,java,indent=0,subs="verbatim"]
|
|
----
|
|
include::{docs-java}/howto/testing/slicetests/MySecurityConfiguration.java[]
|
|
----
|
|
|
|
[source,java,indent=0,subs="verbatim"]
|
|
----
|
|
include::{docs-java}/howto/testing/slicetests/MyDatasourceConfiguration.java[]
|
|
----
|
|
|
|
Having a single configuration class can be inefficient when beans of a certain domain need to be included in slice tests.
|
|
Instead, structuring the application's configuration as multiple granular classes with beans for a specific domain can enable importing them only for specific slice tests.
|
|
|