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