From 422e6b7d418f1eaffabc835f2ee4c29f05613bd5 Mon Sep 17 00:00:00 2001 From: Justin Griffin Date: Sun, 14 Oct 2018 21:20:54 -0400 Subject: [PATCH 1/2] Support expressing application `args` in `@SpringBootTest` Add `args` property to the `@SpringBootTest` annotation so tests can easily supply application arguments to pass to their app under test. See gh-14823 --- .../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 76a77506b1..004928b0df 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 @@ -6752,6 +6752,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 0000000000..bc454fdfa6 --- /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 e68b80c7a3..7e7047abcc 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 @@ public class SpringBootContextLoader extends AbstractContextLoader { application.setWebApplicationType(WebApplicationType.NONE); } application.setInitializers(initializers); - return application.run(); + return application.run(getArgs(config)); } /** @@ -145,6 +145,19 @@ public class SpringBootContextLoader extends AbstractContextLoader { 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 eda5941d12..84d57e75a7 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 @@ public @interface SpringBootTest { */ 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 0000000000..838027b368 --- /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 { + + } + +} From 7413584b0088ce7c9f6227febe50764ef3048a38 Mon Sep 17 00:00:00 2001 From: Stephane Nicoll Date: Wed, 13 Feb 2019 15:05:41 +0100 Subject: [PATCH 2/2] Polish "Support expressing application `args` in `@SpringBootTest`" Closes gh-14823 --- .../main/asciidoc/spring-boot-features.adoc | 12 ++++++----- .../ApplicationArgumentsExampleTests.java | 20 +++++++------------ .../test/context/SpringBootContextLoader.java | 10 +++++----- .../boot/test/context/SpringBootTest.java | 19 +++++++++++------- .../test/context/SpringBootTestArgsTests.java | 14 +++++++------ 5 files changed, 39 insertions(+), 36 deletions(-) rename spring-boot-project/spring-boot-docs/src/{test/java/org/springframework/boot/docs => main/java/org/springframework/boot/docs/test}/context/ApplicationArgumentsExampleTests.java (73%) 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 004928b0df..4aaf614cd6 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 @@ -6752,18 +6752,20 @@ 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 + +[[boot-features-testing-spring-boot-application-arguments]] +==== Using Application Arguments If your application expects <>, you can -have `@SpringBootTest` inject them using the `args` field. +have `@SpringBootTest` inject them using the `args` attribute. [source,java,indent=0] ---- -include::{test-examples}/context/ApplicationArgumentsExampleTests.java[tag=args] -} +include::{code-examples}/test/context/ApplicationArgumentsExampleTests.java[tag=example] ---- + + [[boot-features-testing-spring-boot-applications-testing-with-mock-environment]] ==== Testing with a mock environment By default, `@SpringBootTest` does not start the server. If you have web endpoints that 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/main/java/org/springframework/boot/docs/test/context/ApplicationArgumentsExampleTests.java similarity index 73% rename from spring-boot-project/spring-boot-docs/src/test/java/org/springframework/boot/docs/context/ApplicationArgumentsExampleTests.java rename to spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/test/context/ApplicationArgumentsExampleTests.java index bc454fdfa6..94bd522d8d 100644 --- 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/main/java/org/springframework/boot/docs/test/context/ApplicationArgumentsExampleTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2018 the original author or authors. + * Copyright 2012-2019 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. @@ -14,22 +14,21 @@ * limitations under the License. */ -package org.springframework.boot.docs.context; +package org.springframework.boot.docs.test.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; +// tag::example[] @RunWith(SpringRunner.class) -@SpringBootTest(args = { "--foo=bar" }) +@SpringBootTest(args = "--app.test=one") public class ApplicationArgumentsExampleTests { @Autowired @@ -37,14 +36,9 @@ public class ApplicationArgumentsExampleTests { @Test public void applicationArgumentsPopulated() { - assertThat(this.args.getOptionNames()).contains("foo"); - assertThat(this.args.getOptionValues("foo")).contains("bar"); - } - - // end::args[] - @Configuration - protected static class Config { - + assertThat(this.args.getOptionNames()).containsOnly("app.test"); + assertThat(this.args.getOptionValues("app.test")).containsOnly("one"); } } +// end::example[] 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 7e7047abcc..570aa90610 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 @@ -1,5 +1,5 @@ /* - * Copyright 2012-2018 the original author or authors. + * Copyright 2012-2019 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. @@ -146,11 +146,11 @@ public class SpringBootContextLoader extends AbstractContextLoader { } /** - * Get the {@link SpringBootTest#args()} (if present) specified in the annotated test - * class. If no args given, returns empty array. + * Return the application arguments to use. If no arguments are available, return an + * empty array. * @param config the source context configuration - * @return the {@link SpringBootTest#args()} (if present) specified in the annotated - * test class, or empty array + * @return the application arguments to use + * @see SpringApplication#run(String...) */ protected String[] getArgs(MergedContextConfiguration config) { SpringBootTest annotation = AnnotatedElementUtils 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 84d57e75a7..da67e11093 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 @@ -1,5 +1,5 @@ /* - * Copyright 2012-2018 the original author or authors. + * Copyright 2012-2019 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. @@ -25,6 +25,7 @@ import java.lang.annotation.Target; import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.boot.ApplicationArguments; import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringBootConfiguration; import org.springframework.boot.WebApplicationType; @@ -55,6 +56,8 @@ import org.springframework.web.context.WebApplicationContext; * specified. *
  • Allows custom {@link Environment} properties to be defined using the * {@link #properties() properties attribute}.
  • + *
  • Allows application arguments to be defined using the {@link #args() args + * attribute}.
  • *
  • Provides support for different {@link #webEnvironment() webEnvironment} modes, * including the ability to start a fully running web server listening on a * {@link WebEnvironment#DEFINED_PORT defined} or {@link WebEnvironment#RANDOM_PORT @@ -93,6 +96,14 @@ public @interface SpringBootTest { @AliasFor("value") String[] properties() default {}; + /** + * Application arguments that should be passed to the application under test. + * @return the application arguments to pass to the application under test. + * @see ApplicationArguments + * @see SpringApplication#run(String...) + */ + String[] args() default {}; + /** * The annotated classes to use for loading an * {@link org.springframework.context.ApplicationContext ApplicationContext}. Can also @@ -106,12 +117,6 @@ public @interface SpringBootTest { */ 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 index 838027b368..e2806dbbf9 100644 --- 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 @@ -1,5 +1,5 @@ /* - * Copyright 2012-2017 the original author or authors. + * Copyright 2012-2019 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. @@ -27,13 +27,13 @@ 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. + * Tests for {@link SpringBootTest} with application arguments. * * @author Justin Griffin + * @author Stephane Nicoll */ @RunWith(SpringRunner.class) -@SpringBootTest(args = { "--option.foo=option-foo-value", "other.bar=other-bar-value" }) +@SpringBootTest(args = { "--option.foo=foo-value", "other.bar=other-bar-value" }) public class SpringBootTestArgsTests { @Autowired @@ -41,8 +41,10 @@ public class SpringBootTestArgsTests { @Test public void applicationArgumentsPopulated() { - assertThat(this.args.getOptionNames()).contains("option.foo"); - assertThat(this.args.getNonOptionArgs()).contains("other.bar=other-bar-value"); + assertThat(this.args.getOptionNames()).containsOnly("option.foo"); + assertThat(this.args.getOptionValues("option.foo")).containsOnly("foo-value"); + assertThat(this.args.getNonOptionArgs()) + .containsOnly("other.bar=other-bar-value"); } @Configuration