编写 JUnit 规则:描述不包含我的注释

Writing a JUnit Rule: Description doesn't contain my annotation

我正在尝试编写一个简单的 JUnit 规则实现,如果不成功,它会重新运行一个测试用例给定的次数。

它本身工作正常,但我想使用我附加到方法的自定义注释使其可按方法配置。

这是我的规则实现:

public class Retry implements TestRule {
    private int retryCount = 10;

    @Override
    public Statement apply(Statement base, Description description) {
        return new Statement() {
            public void evaluate() throws Throwable {
                RetryCount annotation = description.getAnnotation(RetryCount.class);
                // Problem is here, the annotation is always null!
                int retries = (annotation != null) ? annotation.retries() : retryCount;

                // keep track of the last failure to include it in our failure later
                AssertionError lastFailure = null;
                for (int i = 0; i < retries; i++) {
                    try {
                        // call wrapped statement and return if successful
                        base.evaluate();
                        return;
                    } catch (AssertionError err) {
                        lastFailure = err;
                    }
                }
                // give meaningful message and include last failure for the
                // error trace
                throw new AssertionError("Gave up after " + retries + " tries", lastFailure);
            }
        };
    }

    // the annotation for method-based retries
    public static @interface RetryCount {
        public int retries() default 1;
    }
}

在我评论的行中,我没有得到附加到方法的注释:

public class UnreliableServiceUnitTest {
    private UnreliableService sut = new UnreliableService();

    @Rule
    public Retry retry = new Retry();

    @Test
    @RetryCount(retries=5) // here it is
    public void worksSometimes() {
        boolean worked = sut.workSometimes();
        assertThat(worked, is(true));
    }
}

如果我调试规则,Description 注释列表包含 @Test 注释但不包含 @RetryCount。我还尝试添加一个 @Deprecated,它也会被添加。

知道为什么吗?

为了完整起见,这是示例 SUT:

public class UnreliableService {
    private static Random RANDOM = new Random();

    // needs at least two calls
    private static int COUNTER = RANDOM.nextInt(8) + 2;

    public boolean workSometimes() {
        if (--COUNTER == 0) {
            COUNTER = RANDOM.nextInt(8) + 2;
            return true;
        }
        return false;
    }
}

@Test 注释是运行时注释。你的 RetryCount 不是那样定义的。它应该是这样您可以在运行时访问它。将您的代码更改为:

// the annotation for method-based retries
@Retention(value=RUNTIME)
public static @interface RetryCount {
    public int retries() default 1;
}

使用 RetentionPolicy Runtime 允许您反射性地阅读注释。参见 here the Javadoc