EnvCondition.java
package redis.clients.jedis.util;
import io.redis.test.annotations.ConditionalOnEnv;
import org.junit.jupiter.api.extension.ConditionEvaluationResult;
import org.junit.jupiter.api.extension.ExecutionCondition;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.platform.commons.util.AnnotationUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Arrays;
import java.util.Optional;
/**
* JUnit 5 execution condition that enables or disables tests based on the test environment.
* <p>
* This condition works with the {@link ConditionalOnEnv} annotation to conditionally execute tests
* depending on the current test environment (e.g., Docker, Redis Enterprise).
* <p>
* The environment is determined using {@link TestEnvUtil}.
* <p>
* Example usage with JUnit 5:
*
* <pre>
* @ExtendWith(EnvCondition.class)
* @ConditionalOnEnv(value = TestEnvUtil.ENV_OSS_DOCKER, enabled = true)
* public class DockerOnlyTest {
* // Tests in this class only run in Docker environment
* }
*
* @ExtendWith(EnvCondition.class)
* @ConditionalOnEnv(value = TestEnvUtil.ENV_REDIS_ENTERPRISE, enabled = false)
* public class NotOnEnterpriseTest {
* // Tests in this class are skipped in Redis Enterprise environment
* }
* </pre>
*/
public class EnvCondition implements ExecutionCondition {
private static final Logger logger = LoggerFactory.getLogger(EnvCondition.class);
@Override
public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context) {
String currentEnv = TestEnvUtil.getTestEnvProvider();
ConditionalOnEnv annotation = getConditionalOnEnvAnnotation(context);
if (annotation != null) {
return evaluateConditionalOnEnv(annotation, currentEnv);
}
return ConditionEvaluationResult.enabled("No @ConditionalOnEnv annotation found");
}
private ConditionEvaluationResult evaluateConditionalOnEnv(ConditionalOnEnv annotation,
String currentEnv) {
String[] envs = annotation.value();
boolean enabled = annotation.enabled();
boolean matches = Arrays.stream(envs).anyMatch(env -> env.equalsIgnoreCase(currentEnv));
if (enabled) {
// enabled = true: test runs ONLY when environment matches
if (matches) {
logger.debug("Test enabled: current environment '{}' matches one of {}", currentEnv,
Arrays.toString(envs));
return ConditionEvaluationResult
.enabled("Current environment '" + currentEnv + "' is in the enabled list");
}
String message = annotation.message();
String disabledReason = message.isEmpty()
? "Test requires environment " + Arrays.toString(envs) + ", but current environment is '"
+ currentEnv + "'"
: message;
logger.debug("Test disabled: {}", disabledReason);
return ConditionEvaluationResult.disabled(disabledReason);
} else {
// enabled = false: test is SKIPPED when environment matches
if (matches) {
String message = annotation.message();
String disabledReason = message.isEmpty()
? "Test is disabled in environment '" + currentEnv + "'"
: message;
logger.debug("Test disabled: {}", disabledReason);
return ConditionEvaluationResult.disabled(disabledReason);
}
logger.debug("Test enabled: current environment '{}' is not in disabled list {}", currentEnv,
Arrays.toString(envs));
return ConditionEvaluationResult
.enabled("Current environment '" + currentEnv + "' is not in the disabled list");
}
}
/**
* Retrieves the {@link ConditionalOnEnv} annotation from the test method or class. Method-level
* annotations take precedence over class-level annotations.
* @param context the extension context
* @return the annotation, or null if not present
*/
private ConditionalOnEnv getConditionalOnEnvAnnotation(ExtensionContext context) {
Optional<ConditionalOnEnv> methodAnnotation = AnnotationUtils
.findAnnotation(context.getTestMethod(), ConditionalOnEnv.class);
if (methodAnnotation.isPresent()) {
return methodAnnotation.get();
}
Optional<ConditionalOnEnv> classAnnotation = AnnotationUtils
.findAnnotation(context.getRequiredTestClass(), ConditionalOnEnv.class);
return classAnnotation.orElse(null);
}
}