【问题标题】:Writing a JUnit Rule: Description doesn't contain my annotation编写 JUnit 规则:描述不包含我的注释
【发布时间】:2018-01-19 09:49:42
【问题描述】:

我正在尝试编写一个简单的 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;
    }
}

【问题讨论】:

    标签: java junit annotations rule


    【解决方案1】:

    @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

    【讨论】:

    • 非常感谢,已解决。很简单,希望在Description#getAnnotation javadoc 中提到它,但对于更习惯于编写注释的人来说,这可能是显而易见的。
    • 是的,我同意应该在某处提及它。但这是你做对后永远不会忘记的事情之一:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-30
    • 2015-12-14
    • 2016-10-30
    • 1970-01-01
    • 2019-03-01
    • 2011-08-24
    相关资源
    最近更新 更多