diff --git a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/features/testing.adoc b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/features/testing.adoc index 772ffa4740..b19a813ae0 100644 --- a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/features/testing.adoc +++ b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/features/testing.adoc @@ -835,6 +835,7 @@ include::code:MyBatchConfiguration[] NOTE: Depending on the complexity of your application, you may either have a single `@Configuration` class for your customizations or one class per domain area. The latter approach lets you enable it in one of your tests, if necessary, with the `@Import` annotation. +See <> for more details on when you might want to enable specific `@Configuration` classes for slice tests. Test slices exclude `@Configuration` classes from scanning. For example, for a `@WebMvcTest`, the following configuration will not include the given `WebMvcConfigurer` bean in the application context loaded by the test slice: diff --git a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/howto/testing.adoc b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/howto/testing.adoc index 95da6a65b4..eca1b1ed64 100644 --- a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/howto/testing.adoc +++ b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/howto/testing.adoc @@ -36,3 +36,36 @@ This can be done with a static `@DynamicPropertySource` method that allows addin include::code:dynamicproperties/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 via 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(MySecurityConfiguration.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 needed 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. + diff --git a/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/howto/testing/slicetests/MyConfiguration.java b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/howto/testing/slicetests/MyConfiguration.java new file mode 100644 index 0000000000..e6d24d1bbe --- /dev/null +++ b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/howto/testing/slicetests/MyConfiguration.java @@ -0,0 +1,43 @@ +/* + * Copyright 2012-2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.docs.howto.testing.slicetests; + +import org.apache.commons.dbcp2.BasicDataSource; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.jdbc.DataSourceBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.web.SecurityFilterChain; + +@Configuration(proxyBeanMethods = false) +public class MyConfiguration { + + @Bean + public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { + http.authorizeRequests().anyRequest().authenticated(); + return http.build(); + } + + @Bean + @ConfigurationProperties("app.datasource.second") + public BasicDataSource secondDataSource() { + return DataSourceBuilder.create().type(BasicDataSource.class).build(); + } + +} diff --git a/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/howto/testing/slicetests/MyDatasourceConfiguration.java b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/howto/testing/slicetests/MyDatasourceConfiguration.java new file mode 100644 index 0000000000..70263ea82b --- /dev/null +++ b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/howto/testing/slicetests/MyDatasourceConfiguration.java @@ -0,0 +1,35 @@ +/* + * Copyright 2012-2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.docs.howto.testing.slicetests; + +import org.apache.commons.dbcp2.BasicDataSource; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.jdbc.DataSourceBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration(proxyBeanMethods = false) +class MyDatasourceConfiguration { + + @Bean + @ConfigurationProperties("app.datasource.second") + public BasicDataSource secondDataSource() { + return DataSourceBuilder.create().type(BasicDataSource.class).build(); + } + +} diff --git a/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/howto/testing/slicetests/MySecurityConfiguration.java b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/howto/testing/slicetests/MySecurityConfiguration.java new file mode 100644 index 0000000000..874d0bd668 --- /dev/null +++ b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/howto/testing/slicetests/MySecurityConfiguration.java @@ -0,0 +1,33 @@ +/* + * Copyright 2012-2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.docs.howto.testing.slicetests; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.web.SecurityFilterChain; + +@Configuration(proxyBeanMethods = false) +class MySecurityConfiguration { + + @Bean + public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { + http.authorizeRequests().anyRequest().authenticated(); + return http.build(); + } + +}