Issue
I'm trying to split my unittests on a gitlab ci runner, therefore i want to annotate my parent test-cass like this
@EnabledIf("#{systemEnvironment['CI_NODE_INDEX'] == null || junitDisplayName.hashCode() % systemEnvironment['CI_NODE_TOTAL'] == systemEnvironment['CI_NODE_INDEX']}")
but i get the exception
Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1008E: Property or field 'junitDisplayName' cannot be found on object of type 'org.springframework.beans.factory.config.BeanExpressionContext' - maybe not public or not valid?
but the docs say there should be such a field: https://junit.org/junit5/docs/5.3.0/api/org/junit/jupiter/api/condition/EnabledIf.html
Solution
I tried out the snippets you provided to search for a fix, but could not find a working solution. To circumvent the issue, I have set up a custom ExecutionCondition
that skips a test(class) when the display name contains the text "disabled", and used @ExtendWith
to include the condition in the Test class:
DemoApplicationTests
package com.example.demo;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
@ExtendWith(CustomExecutionCondition.class)
//@DisplayName("disabled")
class DemoApplicationTests {
@Test
@DisplayName("enabled")
void shouldBeEnabled() {
}
@Test
@DisplayName("disabled")
void shouldBeDisabled() {
throw new IllegalStateException("Should not happen");
}
}
package com.example.demo;
import org.junit.jupiter.api.extension.ConditionEvaluationResult;
import org.junit.jupiter.api.extension.ExecutionCondition;
import org.junit.jupiter.api.extension.ExtensionContext;
public class CustomExecutionCondition implements ExecutionCondition {
@Override
public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context) {
String displayName = context.getDisplayName();
// int ciNodeIndex = Integer.parseInt(System.getProperty("CI_NODE_INDEX"));
// int ciNodeTotal = Integer.parseInt(System.getProperty("CI_NODE_TOTAL"));
if (displayName != null && displayName.contains("disabled")) {
return ConditionEvaluationResult.disabled("Test '" + displayName + "' is disabled");
}
return ConditionEvaluationResult.enabled("Test '" + displayName + "' is enabled");
}
}
I have left out the system property&hashcode evaluation to simplify the example. The condition is evaluated three times; one time for the test class, and two times for the test methods. If the class level evaluation returns false, all the test methods in the class are skipped.
Answered By - Michiel