0

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?

2
  • 1
    JUnit 5 requires extensions to have no-argument constructors when they are registered with @ExtendWith. See Extension for details. The @RequiredArgsConstructor annotation on your class means you don't have a no-argument constructor. Are you asking how to inject dependencies into a JUnit extension? Commented Nov 11, 2023 at 23:22
  • Yes! I tried instead of RequiredArgsConstructor to use AllArgsConstructor and NoArgsConstructor - then i have such error: Failed to evaluate condition [com.mob.market3b.platform.execution.PlatformExecutionCondition]: Cannot invoke "com.mob.market3b.config.EmulatorConfigProperties.getPlatformName()" because "this.emulatorConfigProperties" is null. What can i do @Slaw? Commented Nov 12, 2023 at 9:15

1 Answer 1

3

As @slaw mentioned, your PlatformExecutionCondition must have a default no-args constructor.

Consequently, the fields in PlatformExecutionCondition cannot be final.

Although you could create an instance of PlatformExecutionCondition as a bean in your ApplicationContext and have that injected into a field in the test class annotated with @Autowired and @RegisterExtension (see https://stackoverflow.com/a/50251190/388980), the simplest way to access beans from the ApplicationContext within a custom JUnit Jupiter extension is to retrieve them manually from the ApplicationContext -- for example via getBean(<bean type>).

You can access the application context within your PlatformExecutionCondition via org.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 an ExecutionCondition implementation is generally not recommended since your ExecutionCondition may then effectively force the creation of an ApplicationContext that would otherwise not be used (if the ExecutionCondition ends up disabling the test). See the documentation for @DisabledIf(loadContext) for details.

Side Note

Spring's @EnabledIf and @DisabledIf annotations may be an easier alternative to implementing your own ExecutionCondition.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.