I have custom Interface "Platform" with @ExtendWith annotation and Class which implements ExecutionCondition.
@Documented
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
@ExtendWith(PlatformExecutionCondition.class)
public @interface Platform {
MobilePlatform[] value();
@Component
@RequiredArgsConstructor
public class PlatformExecutionCondition implements ExecutionCondition {
private final EmulatorConfigProperties emulatorConfigProperties;
private final PlatformAnnotationManager platformAnnotationManager;
@Override
public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext extensionContext) {
MobilePlatform platform = MobilePlatform.getByName(emulatorConfigProperties.getPlatformName());
if (platform == null) {
return disabled("Mobile platform is not specified");
}
if (extensionContext.getTestMethod().isEmpty()) {
return enabled("Test class execution enabled");
}
Set<MobilePlatform> mobilePlatforms = platformAnnotationManager.getTestMobilePlatforms(extensionContext);
if (mobilePlatforms.contains(platform)) {
return enabled(format("{0} mobile platform is available for testing", platform.getName()));
} else {
return disabled(format("{0} mobile platform is not available for testing", platform.getName()));
}
}
}
While running the test, I catch an error java.lang.NoSuchMethodException: com.mob.market3b.platform.execution.PlatformExecutionCondition.<init>() If I remove the annotation, the test runs without errors, but then the evaluateExecutionCondition method is not in use. How can I use @ExtendWith annotation with Spring?
As @slaw mentioned, your
PlatformExecutionConditionmust have a default no-args constructor.Consequently, the fields in
PlatformExecutionConditioncannot befinal.Although you could create an instance of
PlatformExecutionConditionas a bean in yourApplicationContextand have that injected into a field in the test class annotated with@Autowiredand@RegisterExtension(see https://stackoverflow.com/a/50251190/388980), the simplest way to access beans from theApplicationContextwithin a custom JUnit Jupiter extension is to retrieve them manually from theApplicationContext-- for example viagetBean(<bean type>).You can access the application context within your
PlatformExecutionConditionviaorg.springframework.test.context.junit.jupiter.SpringExtension.getApplicationContext(ExtensionContext).See also: https://stackoverflow.com/a/56922657/388980
WARNING
Please note that accessing the
ApplicationContext(or beans within the application context) in anExecutionConditionimplementation is generally not recommended since yourExecutionConditionmay then effectively force the creation of anApplicationContextthat would otherwise not be used (if theExecutionConditionends up disabling the test). See the documentation for@DisabledIf(loadContext)for details.Side Note
Spring's
@EnabledIfand@DisabledIfannotations may be an easier alternative to implementing your ownExecutionCondition.