001/*
002 * Copyright 2002-2016 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 *      https://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.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
026/**
027 * {@code @ContextHierarchy} is a class-level annotation that is used to define
028 * a hierarchy of {@link org.springframework.context.ApplicationContext
029 * ApplicationContexts} for integration tests.
030 *
031 * <h3>Examples</h3>
032 * <p>The following JUnit-based examples demonstrate common configuration
033 * scenarios for integration tests that require the use of context hierarchies.
034 *
035 * <h4>Single Test Class with Context Hierarchy</h4>
036 * <p>{@code ControllerIntegrationTests} represents a typical integration testing
037 * scenario for a Spring MVC web application by declaring a context hierarchy
038 * consisting of two levels, one for the <em>root</em> {@code WebApplicationContext}
039 * (with {@code TestAppConfig}) and one for the <em>dispatcher servlet</em>
040 * {@code WebApplicationContext} (with {@code WebConfig}). The {@code
041 * WebApplicationContext} that is <em>autowired</em> into the test instance is
042 * the one for the child context (i.e., the lowest context in the hierarchy).
043 *
044 * <pre class="code">
045 * &#064;RunWith(SpringJUnit4ClassRunner.class)
046 * &#064;WebAppConfiguration
047 * &#064;ContextHierarchy({
048 *     &#064;ContextConfiguration(classes = TestAppConfig.class),
049 *     &#064;ContextConfiguration(classes = WebConfig.class)
050 * })
051 * public class ControllerIntegrationTests {
052 *
053 *     &#064;Autowired
054 *     private WebApplicationContext wac;
055 *
056 *     // ...
057 * }</pre>
058 *
059 * <h4>Class Hierarchy with Implicit Parent Context</h4>
060 * <p>The following test classes define a context hierarchy within a test class
061 * hierarchy. {@code AbstractWebTests} declares the configuration for a root
062 * {@code WebApplicationContext} in a Spring-powered web application. Note,
063 * however, that {@code AbstractWebTests} does not declare {@code @ContextHierarchy};
064 * consequently, subclasses of {@code AbstractWebTests} can optionally participate
065 * in a context hierarchy or follow the standard semantics for {@code @ContextConfiguration}.
066 * {@code SoapWebServiceTests} and {@code RestWebServiceTests} both extend
067 * {@code AbstractWebTests} and define a context hierarchy via {@code @ContextHierarchy}.
068 * The result is that three application contexts will be loaded (one for each
069 * declaration of {@code @ContextConfiguration}, and the application context
070 * loaded based on the configuration in {@code AbstractWebTests} will be set as
071 * the parent context for each of the contexts loaded for the concrete subclasses.
072 *
073 * <pre class="code">
074 * &#064;RunWith(SpringJUnit4ClassRunner.class)
075 * &#064;WebAppConfiguration
076 * &#064;ContextConfiguration("file:src/main/webapp/WEB-INF/applicationContext.xml")
077 * public abstract class AbstractWebTests {}
078 *
079 * &#064;ContextHierarchy(&#064;ContextConfiguration("/spring/soap-ws-config.xml")
080 * public class SoapWebServiceTests extends AbstractWebTests {}
081 *
082 * &#064;ContextHierarchy(&#064;ContextConfiguration("/spring/rest-ws-config.xml")
083 * public class RestWebServiceTests extends AbstractWebTests {}</pre>
084 *
085 * <h4>Class Hierarchy with Merged Context Hierarchy Configuration</h4>
086 * <p>The following classes demonstrate the use of <em>named</em> hierarchy levels
087 * in order to <em>merge</em> the configuration for specific levels in a context
088 * hierarchy. {@code BaseTests} defines two levels in the hierarchy, {@code parent}
089 * and {@code child}. {@code ExtendedTests} extends {@code BaseTests} and instructs
090 * the Spring TestContext Framework to merge the context configuration for the
091 * {@code child} hierarchy level, simply by ensuring that the names declared via
092 * {@link ContextConfiguration#name} are both {@code "child"}. The result is that
093 * three application contexts will be loaded: one for {@code "/app-config.xml"},
094 * one for {@code "/user-config.xml"}, and one for <code>{"/user-config.xml",
095 * "/order-config.xml"}</code>. As with the previous example, the application
096 * context loaded from {@code "/app-config.xml"} will be set as the parent context
097 * for the contexts loaded from {@code "/user-config.xml"} and <code>{"/user-config.xml",
098 * "/order-config.xml"}</code>.
099 *
100 * <pre class="code">
101 * &#064;RunWith(SpringJUnit4ClassRunner.class)
102 * &#064;ContextHierarchy({
103 *     &#064;ContextConfiguration(name = "parent", locations = "/app-config.xml"),
104 *     &#064;ContextConfiguration(name = "child",  locations = "/user-config.xml")
105 * })
106 * public class BaseTests {}
107 *
108 * &#064;ContextHierarchy(
109 *     &#064;ContextConfiguration(name = "child",  locations = "/order-config.xml")
110 * )
111 * public class ExtendedTests extends BaseTests {}</pre>
112 *
113 * <h4>Class Hierarchy with Overridden Context Hierarchy Configuration</h4>
114 * <p>In contrast to the previous example, this example demonstrates how to
115 * <em>override</em> the configuration for a given named level in a context hierarchy
116 * by setting the {@link ContextConfiguration#inheritLocations} flag to {@code false}.
117 * Consequently, the application context for {@code ExtendedTests} will be loaded
118 * only from {@code "/test-user-config.xml"} and will have its parent set to the
119 * context loaded from {@code "/app-config.xml"}.
120 *
121 * <pre class="code">
122 * &#064;RunWith(SpringJUnit4ClassRunner.class)
123 * &#064;ContextHierarchy({
124 *     &#064;ContextConfiguration(name = "parent", locations = "/app-config.xml"),
125 *     &#064;ContextConfiguration(name = "child",  locations = "/user-config.xml")
126 * })
127 * public class BaseTests {}
128 *
129 * &#064;ContextHierarchy(
130 *     &#064;ContextConfiguration(name = "child",  locations = "/test-user-config.xml", inheritLocations=false)
131 * )
132 * public class ExtendedTests extends BaseTests {}</pre>
133 *
134 * <p>As of Spring Framework 4.0, this annotation may be used as a
135 * <em>meta-annotation</em> to create custom <em>composed annotations</em>.
136 *
137 * @author Sam Brannen
138 * @since 3.2.2
139 * @see ContextConfiguration
140 * @see org.springframework.context.ApplicationContext
141 */
142@Target(ElementType.TYPE)
143@Retention(RetentionPolicy.RUNTIME)
144@Documented
145@Inherited
146public @interface ContextHierarchy {
147
148        /**
149         * A list of {@link ContextConfiguration @ContextConfiguration} instances,
150         * each of which defines a level in the context hierarchy.
151         * <p>If you need to merge or override the configuration for a given level
152         * of the context hierarchy within a test class hierarchy, you must explicitly
153         * name that level by supplying the same value to the {@link ContextConfiguration#name
154         * name} attribute in {@code @ContextConfiguration} at each level in the
155         * class hierarchy. See the class-level Javadoc for examples.
156         */
157        ContextConfiguration[] value();
158
159}