001/*
002 * Copyright 2012-2018 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.boot.test.context;
018
019import java.lang.annotation.Documented;
020import java.lang.annotation.ElementType;
021import java.lang.annotation.Inherited;
022import java.lang.annotation.Retention;
023import java.lang.annotation.RetentionPolicy;
024import java.lang.annotation.Target;
025
026import org.junit.jupiter.api.extension.ExtendWith;
027
028import org.springframework.boot.SpringApplication;
029import org.springframework.boot.SpringBootConfiguration;
030import org.springframework.boot.WebApplicationType;
031import org.springframework.boot.web.reactive.context.ReactiveWebApplicationContext;
032import org.springframework.boot.web.server.LocalServerPort;
033import org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext;
034import org.springframework.context.ApplicationContext;
035import org.springframework.context.annotation.Configuration;
036import org.springframework.core.annotation.AliasFor;
037import org.springframework.core.env.Environment;
038import org.springframework.test.context.BootstrapWith;
039import org.springframework.test.context.ContextConfiguration;
040import org.springframework.test.context.ContextLoader;
041import org.springframework.test.context.junit.jupiter.SpringExtension;
042import org.springframework.web.context.WebApplicationContext;
043
044/**
045 * Annotation that can be specified on a test class that runs Spring Boot based tests.
046 * Provides the following features over and above the regular <em>Spring TestContext
047 * Framework</em>:
048 * <ul>
049 * <li>Uses {@link SpringBootContextLoader} as the default {@link ContextLoader} when no
050 * specific {@link ContextConfiguration#loader() @ContextConfiguration(loader=...)} is
051 * defined.</li>
052 * <li>Automatically searches for a
053 * {@link SpringBootConfiguration @SpringBootConfiguration} when nested
054 * {@code @Configuration} is not used, and no explicit {@link #classes() classes} are
055 * specified.</li>
056 * <li>Allows custom {@link Environment} properties to be defined using the
057 * {@link #properties() properties attribute}.</li>
058 * <li>Provides support for different {@link #webEnvironment() webEnvironment} modes,
059 * including the ability to start a fully running web server listening on a
060 * {@link WebEnvironment#DEFINED_PORT defined} or {@link WebEnvironment#RANDOM_PORT
061 * random} port.</li>
062 * <li>Registers a {@link org.springframework.boot.test.web.client.TestRestTemplate
063 * TestRestTemplate} and/or
064 * {@link org.springframework.test.web.reactive.server.WebTestClient WebTestClient} bean
065 * for use in web tests that are using a fully running web server.</li>
066 * </ul>
067 *
068 * @author Phillip Webb
069 * @author Andy Wilkinson
070 * @since 1.4.0
071 * @see ContextConfiguration
072 */
073@Target(ElementType.TYPE)
074@Retention(RetentionPolicy.RUNTIME)
075@Documented
076@Inherited
077@BootstrapWith(SpringBootTestContextBootstrapper.class)
078@ExtendWith(SpringExtension.class)
079public @interface SpringBootTest {
080
081        /**
082         * Alias for {@link #properties()}.
083         * @return the properties to apply
084         */
085        @AliasFor("properties")
086        String[] value() default {};
087
088        /**
089         * Properties in form {@literal key=value} that should be added to the Spring
090         * {@link Environment} before the test runs.
091         * @return the properties to add
092         */
093        @AliasFor("value")
094        String[] properties() default {};
095
096        /**
097         * The <em>annotated classes</em> to use for loading an
098         * {@link org.springframework.context.ApplicationContext ApplicationContext}. Can also
099         * be specified using
100         * {@link ContextConfiguration#classes() @ContextConfiguration(classes=...)}. If no
101         * explicit classes are defined the test will look for nested
102         * {@link Configuration @Configuration} classes, before falling back to a
103         * {@link SpringBootConfiguration} search.
104         * @see ContextConfiguration#classes()
105         * @return the annotated classes used to load the application context
106         */
107        Class<?>[] classes() default {};
108
109        /**
110         * The type of web environment to create when applicable. Defaults to
111         * {@link WebEnvironment#MOCK}.
112         * @return the type of web environment
113         */
114        WebEnvironment webEnvironment() default WebEnvironment.MOCK;
115
116        /**
117         * An enumeration web environment modes.
118         */
119        enum WebEnvironment {
120
121                /**
122                 * Creates a {@link WebApplicationContext} with a mock servlet environment if
123                 * servlet APIs are on the classpath, a {@link ReactiveWebApplicationContext} if
124                 * Spring WebFlux is on the classpath or a regular {@link ApplicationContext}
125                 * otherwise.
126                 */
127                MOCK(false),
128
129                /**
130                 * Creates a web application context (reactive or servlet based) and sets a
131                 * {@code server.port=0} {@link Environment} property (which usually triggers
132                 * listening on a random port). Often used in conjunction with a
133                 * {@link LocalServerPort} injected field on the test.
134                 */
135                RANDOM_PORT(true),
136
137                /**
138                 * Creates a (reactive) web application context without defining any
139                 * {@code server.port=0} {@link Environment} property.
140                 */
141                DEFINED_PORT(true),
142
143                /**
144                 * Creates an {@link ApplicationContext} and sets
145                 * {@link SpringApplication#setWebApplicationType(WebApplicationType)} to
146                 * {@link WebApplicationType#NONE}.
147                 */
148                NONE(false);
149
150                private final boolean embedded;
151
152                WebEnvironment(boolean embedded) {
153                        this.embedded = embedded;
154                }
155
156                /**
157                 * Return if the environment uses an {@link ServletWebServerApplicationContext}.
158                 * @return if an {@link ServletWebServerApplicationContext} is used.
159                 */
160                public boolean isEmbedded() {
161                        return this.embedded;
162                }
163
164        }
165
166}