From ff2af08da716d3a847fe95038e87c7e401a2393c Mon Sep 17 00:00:00 2001 From: Justin Griffin Date: Sun, 14 Oct 2018 21:20:54 -0400 Subject: [PATCH] Support expressing app `args` in `@SpringBootTest` annotated tests Add `args` property to the `@SpringBootTest` annotation so tests can easily supply application arguments to pass to their app under test. For example, ``` @SpringBootTest(args = {"--some.option=some-value", "other.arg=other-value"}) public class SpringBootTestArgsTest { @Autowired private ApplicationArguments args; @Test public void applicationArgumentsPopulated() { assertThat(args.getOptionNames()).contains("some.option"); assertThat(args.getNonOptionArgs()).contains("other.arg=other-value"); } } ``` --- .../main/asciidoc/spring-boot-features.adoc | 11 ++++ .../ApplicationArgumentsExampleTests.java | 50 +++++++++++++++++ .../test/context/SpringBootContextLoader.java | 15 +++++- .../boot/test/context/SpringBootTest.java | 6 +++ .../test/context/SpringBootTestArgsTests.java | 53 +++++++++++++++++++ 5 files changed, 134 insertions(+), 1 deletion(-) create mode 100644 spring-boot-project/spring-boot-docs/src/test/java/org/springframework/boot/docs/context/ApplicationArgumentsExampleTests.java create mode 100644 spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/context/SpringBootTestArgsTests.java diff --git a/spring-boot-project/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc b/spring-boot-project/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc index 13f9cd1abb11..67ce4379acf3 100644 --- a/spring-boot-project/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc +++ b/spring-boot-project/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc @@ -6660,6 +6660,17 @@ NOTE: If you directly use `@ComponentScan` (that is, not through `@SpringBootApplication`) you 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-arguments]] +==== Testing with Application Arguments + +If your application expects <>, you can +have `@SpringBootTest` inject them using the `args` field. + +[source,java,indent=0] +---- +include::{test-examples}/context/ApplicationArgumentsExampleTests.java[tag=args] +} +---- [[boot-features-testing-spring-boot-applications-testing-with-mock-environment]] ==== Testing with a mock environment diff --git a/spring-boot-project/spring-boot-docs/src/test/java/org/springframework/boot/docs/context/ApplicationArgumentsExampleTests.java b/spring-boot-project/spring-boot-docs/src/test/java/org/springframework/boot/docs/context/ApplicationArgumentsExampleTests.java new file mode 100644 index 000000000000..bc454fdfa62f --- /dev/null +++ b/spring-boot-project/spring-boot-docs/src/test/java/org/springframework/boot/docs/context/ApplicationArgumentsExampleTests.java @@ -0,0 +1,50 @@ +/* + * Copyright 2012-2018 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.docs.context; + +// tag::args[] +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.ApplicationArguments; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Configuration; +import org.springframework.test.context.junit4.SpringRunner; + +import static org.assertj.core.api.Assertions.assertThat; + +@RunWith(SpringRunner.class) +@SpringBootTest(args = { "--foo=bar" }) +public class ApplicationArgumentsExampleTests { + + @Autowired + private ApplicationArguments args; + + @Test + public void applicationArgumentsPopulated() { + assertThat(this.args.getOptionNames()).contains("foo"); + assertThat(this.args.getOptionValues("foo")).contains("bar"); + } + + // end::args[] + @Configuration + protected static class Config { + + } + +} diff --git a/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/context/SpringBootContextLoader.java b/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/context/SpringBootContextLoader.java index e68b80c7a39b..7e7047abcc86 100644 --- a/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/context/SpringBootContextLoader.java +++ b/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/context/SpringBootContextLoader.java @@ -124,7 +124,7 @@ else if (config instanceof ReactiveWebMergedContextConfiguration) { application.setWebApplicationType(WebApplicationType.NONE); } application.setInitializers(initializers); - return application.run(); + return application.run(getArgs(config)); } /** @@ -145,6 +145,19 @@ protected ConfigurableEnvironment getEnvironment() { return new StandardEnvironment(); } + /** + * Get the {@link SpringBootTest#args()} (if present) specified in the annotated test + * class. If no args given, returns empty array. + * @param config the source context configuration + * @return the {@link SpringBootTest#args()} (if present) specified in the annotated + * test class, or empty array + */ + protected String[] getArgs(MergedContextConfiguration config) { + SpringBootTest annotation = AnnotatedElementUtils + .findMergedAnnotation(config.getTestClass(), SpringBootTest.class); + return (annotation != null) ? annotation.args() : new String[0]; + } + private void setActiveProfiles(ConfigurableEnvironment environment, String[] profiles) { TestPropertyValues diff --git a/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/context/SpringBootTest.java b/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/context/SpringBootTest.java index eda5941d129f..84d57e75a711 100644 --- a/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/context/SpringBootTest.java +++ b/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/context/SpringBootTest.java @@ -106,6 +106,12 @@ */ Class[] classes() default {}; + /** + * Arguments that should be passed to the application under test. + * @return the arguments to pass to the application under test. + */ + String[] args() default {}; + /** * The type of web environment to create when applicable. Defaults to * {@link WebEnvironment#MOCK}. diff --git a/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/context/SpringBootTestArgsTests.java b/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/context/SpringBootTestArgsTests.java new file mode 100644 index 000000000000..838027b368c4 --- /dev/null +++ b/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/context/SpringBootTestArgsTests.java @@ -0,0 +1,53 @@ +/* + * 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.test.context; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.ApplicationArguments; +import org.springframework.context.annotation.Configuration; +import org.springframework.test.context.junit4.SpringRunner; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Assert that tests annotated with {@link SpringBootTest} can specify + * {@link SpringBootTest#args()} to be passed to their application under test. + * + * @author Justin Griffin + */ +@RunWith(SpringRunner.class) +@SpringBootTest(args = { "--option.foo=option-foo-value", "other.bar=other-bar-value" }) +public class SpringBootTestArgsTests { + + @Autowired + private ApplicationArguments args; + + @Test + public void applicationArgumentsPopulated() { + assertThat(this.args.getOptionNames()).contains("option.foo"); + assertThat(this.args.getNonOptionArgs()).contains("other.bar=other-bar-value"); + } + + @Configuration + protected static class Config { + + } + +}