如何将此测试规则转换为 JUnit5?
How do I convert this test rule to JUnit5?
我有一些使用 junit4 的自定义规则,我想将其转换为 junit5。但是我找不到关于迁移 MethodRule 实现的好文档,除了我应该使用 junit5 扩展而不是规则。
public class MyRule implements MethodRule {
private static final Logger LOGGER = LoggerFactory.getLogger(MyRule.class);
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyAnnotation { }
@Override
public Statement apply(final Statement statement, final FrameworkMethod frameworkMethod, final Object o) {
Statement result = statement;
if (hasMyAnnotation(frameworkMethod)) {
result = new Statement() {
@Override
public void evaluate() {
LOGGER.info("Skipping test");
}
};
}
}
return result;
}
private static boolean hasMyAnnotation(final Annotatable frameworkMethod) {
return frameworkMethod.getAnnotation(MyAnnotation.class) != null;
}
我的 class 正在使用 junit4 Statement
、FrameworkMethod
等来查明我的方法是否有注释...然后跳过它。我该如何转换?
解决方案 1,使用自定义注释禁用测试
JUnit 5 提供了一种扩展,可以控制测试是否应该 运行。这是通过实现 ExecutionCondition 接口来定义的。
扩展实现:
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.logging.Logger;
import org.junit.platform.commons.logging.LoggerFactory;
import org.junit.platform.commons.util.AnnotationUtils;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
public class SkipConditionExtension implements ExecutionCondition {
private static final Logger LOGGER = LoggerFactory.getLogger(SkipConditionExtension.class);
@Override
public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context) {
AnnotatedElement element = context.getElement().orElse(null);
if (hasMyAnnotation(element, MyAnnotation.class)) {
LOGGER.info(() ->"Skipping test");
return ConditionEvaluationResult.disabled(String.format("Skipped test: %s by @MyAnnotation", element));
}
return ConditionEvaluationResult.enabled("Test enabled");
}
private <T extends Annotation> boolean hasMyAnnotation(final AnnotatedElement element, Class<T> annotation) {
return element != null && AnnotationUtils.findAnnotation(element, annotation).isPresent();
}
}
注册字符串扩展:
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
@ExtendWith(SkipConditionExtension.class)
public class TestObject {
@Test
public void test1() {
}
@Test
@MyAnnotation
public void test2() {
}
}
输出:
INFO: Skipping test
Skipped test: public void com.test.TestObject.test2() by @MyAnnotation
方案二,通过调用拦截器跳过测试
InvocationInterceptor 接口为希望拦截测试调用的扩展定义了 API。
当前实施的行为 与您以前的 Rule
完全一样。
扩展实现:
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.InvocationInterceptor;
import org.junit.jupiter.api.extension.ReflectiveInvocationContext;
import org.junit.platform.commons.logging.Logger;
import org.junit.platform.commons.logging.LoggerFactory;
import org.junit.platform.commons.util.AnnotationUtils;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Method;
public class SkipCondition implements InvocationInterceptor {
private static final Logger LOGGER = LoggerFactory.getLogger(SkipConditionExtension.class);
@Override
public void interceptTestMethod(Invocation<Void> invocation, ReflectiveInvocationContext<Method> invocationContext, ExtensionContext extensionContext) throws Throwable {
AnnotatedElement element = extensionContext.getElement().orElse(null);
if (hasMyAnnotation(element, MyAnnotation.class)) {
LOGGER.info(() ->"Skipping test");
invocation.skip();
} else {
invocation.proceed();
}
}
private <T extends Annotation> boolean hasMyAnnotation(final AnnotatedElement element, Class<T> annotation) {
return element != null && AnnotationUtils.findAnnotation(element, annotation).isPresent();
}
}
注册字符串扩展:
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
@ExtendWith(SkipCondition.class)
public class TestObject {
@Test
public void test1() {
}
@Test
@MyAnnotation
public void test2() {
}
}
请注意,您可以根据documentation进行自动分机注册。
我有一些使用 junit4 的自定义规则,我想将其转换为 junit5。但是我找不到关于迁移 MethodRule 实现的好文档,除了我应该使用 junit5 扩展而不是规则。
public class MyRule implements MethodRule {
private static final Logger LOGGER = LoggerFactory.getLogger(MyRule.class);
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyAnnotation { }
@Override
public Statement apply(final Statement statement, final FrameworkMethod frameworkMethod, final Object o) {
Statement result = statement;
if (hasMyAnnotation(frameworkMethod)) {
result = new Statement() {
@Override
public void evaluate() {
LOGGER.info("Skipping test");
}
};
}
}
return result;
}
private static boolean hasMyAnnotation(final Annotatable frameworkMethod) {
return frameworkMethod.getAnnotation(MyAnnotation.class) != null;
}
我的 class 正在使用 junit4 Statement
、FrameworkMethod
等来查明我的方法是否有注释...然后跳过它。我该如何转换?
解决方案 1,使用自定义注释禁用测试
JUnit 5 提供了一种扩展,可以控制测试是否应该 运行。这是通过实现 ExecutionCondition 接口来定义的。
扩展实现:
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.logging.Logger;
import org.junit.platform.commons.logging.LoggerFactory;
import org.junit.platform.commons.util.AnnotationUtils;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
public class SkipConditionExtension implements ExecutionCondition {
private static final Logger LOGGER = LoggerFactory.getLogger(SkipConditionExtension.class);
@Override
public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context) {
AnnotatedElement element = context.getElement().orElse(null);
if (hasMyAnnotation(element, MyAnnotation.class)) {
LOGGER.info(() ->"Skipping test");
return ConditionEvaluationResult.disabled(String.format("Skipped test: %s by @MyAnnotation", element));
}
return ConditionEvaluationResult.enabled("Test enabled");
}
private <T extends Annotation> boolean hasMyAnnotation(final AnnotatedElement element, Class<T> annotation) {
return element != null && AnnotationUtils.findAnnotation(element, annotation).isPresent();
}
}
注册字符串扩展:
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
@ExtendWith(SkipConditionExtension.class)
public class TestObject {
@Test
public void test1() {
}
@Test
@MyAnnotation
public void test2() {
}
}
输出:
INFO: Skipping test
Skipped test: public void com.test.TestObject.test2() by @MyAnnotation
方案二,通过调用拦截器跳过测试
InvocationInterceptor 接口为希望拦截测试调用的扩展定义了 API。
当前实施的行为 与您以前的 Rule
完全一样。
扩展实现:
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.InvocationInterceptor;
import org.junit.jupiter.api.extension.ReflectiveInvocationContext;
import org.junit.platform.commons.logging.Logger;
import org.junit.platform.commons.logging.LoggerFactory;
import org.junit.platform.commons.util.AnnotationUtils;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Method;
public class SkipCondition implements InvocationInterceptor {
private static final Logger LOGGER = LoggerFactory.getLogger(SkipConditionExtension.class);
@Override
public void interceptTestMethod(Invocation<Void> invocation, ReflectiveInvocationContext<Method> invocationContext, ExtensionContext extensionContext) throws Throwable {
AnnotatedElement element = extensionContext.getElement().orElse(null);
if (hasMyAnnotation(element, MyAnnotation.class)) {
LOGGER.info(() ->"Skipping test");
invocation.skip();
} else {
invocation.proceed();
}
}
private <T extends Annotation> boolean hasMyAnnotation(final AnnotatedElement element, Class<T> annotation) {
return element != null && AnnotationUtils.findAnnotation(element, annotation).isPresent();
}
}
注册字符串扩展:
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
@ExtendWith(SkipCondition.class)
public class TestObject {
@Test
public void test1() {
}
@Test
@MyAnnotation
public void test2() {
}
}
请注意,您可以根据documentation进行自动分机注册。