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.junit4.statements;
018
019import java.lang.annotation.Annotation;
020import java.lang.reflect.Method;
021
022import org.junit.AssumptionViolatedException;
023import org.junit.runners.model.Statement;
024
025import org.springframework.core.annotation.AnnotatedElementUtils;
026import org.springframework.test.annotation.IfProfileValue;
027import org.springframework.test.annotation.ProfileValueUtils;
028import org.springframework.util.Assert;
029
030/**
031 * {@code ProfileValueChecker} is a custom JUnit {@link Statement} that checks
032 * whether a test class or test method is enabled in the current environment
033 * via Spring's {@link IfProfileValue @IfProfileValue} annotation.
034 *
035 * @author Sam Brannen
036 * @author Philippe Marschall
037 * @since 4.2
038 * @see #evaluate()
039 * @see IfProfileValue
040 * @see ProfileValueUtils
041 */
042public class ProfileValueChecker extends Statement {
043
044        private final Statement next;
045
046        private final Class<?> testClass;
047
048        private final Method testMethod;
049
050
051        /**
052         * Construct a new {@code ProfileValueChecker} statement.
053         * @param next the next {@code Statement} in the execution chain;
054         * never {@code null}
055         * @param testClass the test class to check; never {@code null}
056         * @param testMethod the test method to check; may be {@code null} if
057         * this {@code ProfileValueChecker} is being applied at the class level
058         */
059        public ProfileValueChecker(Statement next, Class<?> testClass, Method testMethod) {
060                Assert.notNull(next, "The next statement must not be null");
061                Assert.notNull(testClass, "The test class must not be null");
062                this.next = next;
063                this.testClass = testClass;
064                this.testMethod = testMethod;
065        }
066
067
068        /**
069         * Determine if the test specified by arguments to the
070         * {@linkplain #ProfileValueChecker constructor} is <em>enabled</em> in
071         * the current environment, as configured via the {@link IfProfileValue
072         * &#064;IfProfileValue} annotation.
073         * <p>If the test is not annotated with {@code @IfProfileValue} it is
074         * considered enabled.
075         * <p>If a test is not enabled, this method will abort further evaluation
076         * of the execution chain with a failed assumption; otherwise, this method
077         * will simply evaluate the next {@link Statement} in the execution chain.
078         * @see ProfileValueUtils#isTestEnabledInThisEnvironment(Class)
079         * @see ProfileValueUtils#isTestEnabledInThisEnvironment(Method, Class)
080         * @throws AssumptionViolatedException if the test is disabled
081         * @throws Throwable if evaluation of the next statement fails
082         */
083        @Override
084        public void evaluate() throws Throwable {
085                if (this.testMethod == null) {
086                        if (!ProfileValueUtils.isTestEnabledInThisEnvironment(this.testClass)) {
087                                Annotation ann = AnnotatedElementUtils.findMergedAnnotation(this.testClass, IfProfileValue.class);
088                                throw new AssumptionViolatedException(String.format(
089                                                "Profile configured via [%s] is not enabled in this environment for test class [%s].",
090                                                ann, this.testClass.getName()));
091                        }
092                }
093                else {
094                        if (!ProfileValueUtils.isTestEnabledInThisEnvironment(this.testMethod, this.testClass)) {
095                                throw new AssumptionViolatedException(String.format(
096                                                "Profile configured via @IfProfileValue is not enabled in this environment for test method [%s].",
097                                                this.testMethod));
098                        }
099                }
100
101                this.next.evaluate();
102        }
103
104}