Add "testing your auto-configuration" doc section
Closes gh-10011
This commit is contained in:
parent
175f451b0f
commit
e274f29018
|
@ -53,6 +53,7 @@ Phillip Webb; Dave Syer; Josh Long; Stéphane Nicoll; Rob Winch; Andy Wilkinson;
|
|||
:propdeps-plugin: https://github.com/spring-projects/gradle-plugins/tree/master/propdeps-plugin
|
||||
:ant-manual: http://ant.apache.org/manual
|
||||
:code-examples: ../java/org/springframework/boot
|
||||
:test-examples: ../../test/java/org/springframework/boot
|
||||
:gradle-user-guide: https://docs.gradle.org/4.2.1/userguide
|
||||
:hibernate-documentation: http://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/Hibernate_User_Guide.html
|
||||
:jetty-documentation: https://www.eclipse.org/jetty/documentation/9.4.x
|
||||
|
|
|
@ -7101,6 +7101,66 @@ result of a {spring-reference}core.html#expressions[SpEL expression].
|
|||
|
||||
|
||||
|
||||
[[boot-features-test-autoconfig]]
|
||||
=== Testing your auto-configuration
|
||||
An auto-configuration can be affected by many factors: user configuration (`@Bean`
|
||||
definition and `Environment` customization), condition evaluation (presence of a
|
||||
particular library), etc. Concretely, each test should create a well-defined
|
||||
`ApplicationContext` that represents a combination of those customizations and
|
||||
`ApplicationContextRunner` provides a great way to achieve that.
|
||||
|
||||
`ApplicationContextRunner` is usually defined as a field of the test class to gather the
|
||||
base, common configuration. The following makes sure that `UserServiceAutoConfiguration`
|
||||
is always invoked:
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::{test-examples}/autoconfigure/UserServiceAutoConfigurationTests.java[tag=runner]
|
||||
----
|
||||
|
||||
TIP: If multiple auto-configurations have to be defined, there is no need to order their
|
||||
declarations as they will be invoked in the exact same order as when running the
|
||||
application.
|
||||
|
||||
Each test can use the runner to represents a particular use case. For instance, the sample
|
||||
below invokes a user configuration (`UserConfiguration`) and checks that the
|
||||
auto-configuration backs off properly. Invoking `run` provides a callback context that can
|
||||
be used with `Assert4J`:
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::{test-examples}/autoconfigure/UserServiceAutoConfigurationTests.java[tag=test-user-config]
|
||||
----
|
||||
|
||||
It is also possible to easily customize the `Environment`:
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::{test-examples}/autoconfigure/UserServiceAutoConfigurationTests.java[tag=test-env]
|
||||
----
|
||||
|
||||
|
||||
|
||||
==== Simulating a web context
|
||||
If you need to test an auto-configuration that only operates in a Servlet or Reactive web
|
||||
application context, use the `WebApplicationContextRunner` or
|
||||
`ReactiveWebApplicationContextRunner` respectively.
|
||||
|
||||
|
||||
|
||||
==== Overriding the classpath
|
||||
It is also possible to test what happens when a particular class and/or package is not
|
||||
present at runtime. Spring Boot ships with a `FilteredClassLoader` that can easily be used
|
||||
by the runner. In the example below, we assert that if `UserService` is not present, the
|
||||
auto-configuration will be properly disabled:
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::{test-examples}/autoconfigure/UserServiceAutoConfigurationTests.java[tag=test-classloader]
|
||||
----
|
||||
|
||||
|
||||
|
||||
[[boot-features-custom-starter]]
|
||||
=== Creating Your Own Starter
|
||||
A full Spring Boot starter for a library may contain the following components:
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright 2012-2017 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
|
||||
*
|
||||
* http://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.autoconfigure;
|
||||
|
||||
/**
|
||||
* Simple service.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
class UserService {
|
||||
|
||||
private final String name;
|
||||
|
||||
UserService(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Copyright 2012-2017 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
|
||||
*
|
||||
* http://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.autoconfigure;
|
||||
|
||||
import org.springframework.boot.autoconfigure.UserServiceAutoConfiguration.UserProperties;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* Sample auto-configuration.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnClass(UserService.class)
|
||||
@EnableConfigurationProperties(UserProperties.class)
|
||||
public class UserServiceAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public UserService userService(UserProperties properties) {
|
||||
return new UserService(properties.getName());
|
||||
}
|
||||
|
||||
|
||||
@ConfigurationProperties("user")
|
||||
static class UserProperties {
|
||||
|
||||
private String name = "test";
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* Copyright 2012-2017 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
|
||||
*
|
||||
* http://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.autoconfigure;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.boot.test.context.FilteredClassLoader;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link UserServiceAutoConfiguration}.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
public class UserServiceAutoConfigurationTests {
|
||||
|
||||
// tag::runner[]
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(UserServiceAutoConfiguration.class));
|
||||
// end::runner[]
|
||||
|
||||
// tag::test-env[]
|
||||
@Test
|
||||
public void serviceNameCanBeConfigured() {
|
||||
this.contextRunner.withPropertyValues("user.name=test123")
|
||||
.run((context) -> {
|
||||
assertThat(context).hasSingleBean(UserService.class);
|
||||
assertThat(context.getBean(UserService.class).getName())
|
||||
.isEqualTo("test123");
|
||||
});
|
||||
}
|
||||
// end::test-env[]
|
||||
|
||||
// tag::test-classloader[]
|
||||
@Test
|
||||
public void serviceIsIgnoredIfLibraryIsNotPresent() {
|
||||
this.contextRunner.withClassLoader(new FilteredClassLoader(UserService.class))
|
||||
.run((context) -> {
|
||||
assertThat(context).doesNotHaveBean("userService");
|
||||
});
|
||||
}
|
||||
// end::test-classloader[]
|
||||
|
||||
|
||||
// tag::test-user-config[]
|
||||
@Test
|
||||
public void defaultServiceBacksOff() {
|
||||
this.contextRunner.withUserConfiguration(UserConfiguration.class)
|
||||
.run((context) -> {
|
||||
assertThat(context).hasSingleBean(UserService.class);
|
||||
assertThat(context.getBean(UserService.class)).isSameAs(
|
||||
context.getBean(UserConfiguration.class).myUserService());
|
||||
});
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class UserConfiguration {
|
||||
|
||||
@Bean
|
||||
public UserService myUserService() {
|
||||
return new UserService("mine");
|
||||
}
|
||||
|
||||
}
|
||||
// end::test-user-config[]
|
||||
|
||||
}
|
Loading…
Reference in New Issue