001/*
002 * Copyright 2002-2019 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.io.Serializable;
020import java.lang.reflect.Method;
021import java.util.function.Function;
022
023import org.springframework.context.ApplicationContext;
024import org.springframework.context.ApplicationEvent;
025import org.springframework.core.AttributeAccessor;
026import org.springframework.lang.Nullable;
027import org.springframework.test.annotation.DirtiesContext.HierarchyMode;
028
029/**
030 * {@code TestContext} encapsulates the context in which a test is executed,
031 * agnostic of the actual testing framework in use.
032 *
033 * <p>As of Spring Framework 5.0, concrete implementations are highly encouraged
034 * to implement a <em>copy constructor</em> in order to allow the immutable state
035 * and attributes of a {@code TestContext} to be used as a template for additional
036 * contexts created for parallel test execution. The copy constructor must accept a
037 * single argument of the type of the concrete implementation. Any implementation
038 * that does not provide a copy constructor will likely fail in an environment
039 * that executes tests concurrently.
040 *
041 * @author Sam Brannen
042 * @since 2.5
043 * @see TestContextManager
044 * @see TestExecutionListener
045 */
046// Suppression required due to bug in javac in Java 8: presence of default method in a Serializable interface
047@SuppressWarnings("serial")
048public interface TestContext extends AttributeAccessor, Serializable {
049
050        /**
051         * Determine if the {@linkplain ApplicationContext application context} for
052         * this test context is known to be available.
053         * <p>If this method returns {@code true}, a subsequent invocation of
054         * {@link #getApplicationContext()} should succeed.
055         * <p>The default implementation of this method always returns {@code false}.
056         * Custom {@code TestContext} implementations are therefore highly encouraged
057         * to override this method with a more meaningful implementation. Note that
058         * the standard {@code TestContext} implementation in Spring overrides this
059         * method appropriately.
060         * @return {@code true} if the application context has already been loaded
061         * @since 5.2
062         * @see #getApplicationContext()
063         */
064        default boolean hasApplicationContext() {
065                return false;
066        }
067
068        /**
069         * Get the {@linkplain ApplicationContext application context} for this
070         * test context, possibly cached.
071         * <p>Implementations of this method are responsible for loading the
072         * application context if the corresponding context has not already been
073         * loaded, potentially caching the context as well.
074         * @return the application context (never {@code null})
075         * @throws IllegalStateException if an error occurs while retrieving the
076         * application context
077         * @see #hasApplicationContext()
078         */
079        ApplicationContext getApplicationContext();
080
081        /**
082         * Publish the {@link ApplicationEvent} created by the given {@code eventFactory}
083         * to the {@linkplain ApplicationContext application context} for this
084         * test context.
085         * <p>The {@code ApplicationEvent} will only be published if the application
086         * context for this test context {@linkplain #hasApplicationContext() is available}.
087         * @param eventFactory factory for lazy creation of the {@code ApplicationEvent}
088         * @since 5.2
089         * @see #hasApplicationContext()
090         * @see #getApplicationContext()
091         */
092        default void publishEvent(Function<TestContext, ? extends ApplicationEvent> eventFactory) {
093                if (hasApplicationContext()) {
094                        getApplicationContext().publishEvent(eventFactory.apply(this));
095                }
096        }
097
098        /**
099         * Get the {@linkplain Class test class} for this test context.
100         * @return the test class (never {@code null})
101         */
102        Class<?> getTestClass();
103
104        /**
105         * Get the current {@linkplain Object test instance} for this test context.
106         * <p>Note: this is a mutable property.
107         * @return the current test instance (never {@code null})
108         * @see #updateState(Object, Method, Throwable)
109         */
110        Object getTestInstance();
111
112        /**
113         * Get the current {@linkplain Method test method} for this test context.
114         * <p>Note: this is a mutable property.
115         * @return the current test method (never {@code null})
116         * @see #updateState(Object, Method, Throwable)
117         */
118        Method getTestMethod();
119
120        /**
121         * Get the {@linkplain Throwable exception} that was thrown during execution
122         * of the {@linkplain #getTestMethod() test method}.
123         * <p>Note: this is a mutable property.
124         * @return the exception that was thrown, or {@code null} if no exception was thrown
125         * @see #updateState(Object, Method, Throwable)
126         */
127        @Nullable
128        Throwable getTestException();
129
130        /**
131         * Call this method to signal that the {@linkplain ApplicationContext application
132         * context} associated with this test context is <em>dirty</em> and should be
133         * removed from the context cache.
134         * <p>Do this if a test has modified the context &mdash; for example, by
135         * modifying the state of a singleton bean, modifying the state of an embedded
136         * database, etc.
137         * @param hierarchyMode the context cache clearing mode to be applied if the
138         * context is part of a hierarchy (may be {@code null})
139         */
140        void markApplicationContextDirty(@Nullable HierarchyMode hierarchyMode);
141
142        /**
143         * Update this test context to reflect the state of the currently executing test.
144         * <p><strong>WARNING</strong>: This method should only be invoked by the
145         * {@link TestContextManager}.
146         * <p>Caution: concurrent invocations of this method might not be thread-safe,
147         * depending on the underlying implementation.
148         * @param testInstance the current test instance (may be {@code null})
149         * @param testMethod the current test method (may be {@code null})
150         * @param testException the exception that was thrown in the test method,
151         * or {@code null} if no exception was thrown
152         */
153        void updateState(@Nullable Object testInstance, @Nullable Method testMethod, @Nullable Throwable testException);
154
155}