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

时间:2018-01-19 09:49:43

标签: java junit annotations rule

我正在尝试编写一个简单的JUnit Rule实现,如果不成功,它会在一定时间内重新运行测试用例。

它可以正常工作,但我想使用我附加到方法的自定义注释使每个方法可配置。

这是我的规则实施:

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;
    }
}

1 个答案:

答案 0 :(得分:2)

@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