1

我希望整个代码中的断言失败导致我的测试失败。

我有一个这样的 JUnit 规则:

public class AcmeTestRule implements TestRule {
    @Override
    public Statement apply(final Statement statement, Description description) {
        return new Statement() {
            @Override
            public void evaluate() throws Throwable {
                ClassLoader classLoader = getClass().getClassLoader();
                classLoader.clearAssertionStatus();
                classLoader.setDefaultAssertionStatus(true);
                //classLoader.setPackageAssertionStatus("com.acme", true); // no effect

                statement.evaluate();
            }
        }
    }
}

它位于这样的基础测试类上:

public abstract class AcmeTestCase {
    @ClassRule
    public static final AcmeTestRule acmeTestRule = new AcmeTestRule();
}

然后为了确认规则本身是否有效,我进行了以下测试:

public class TestAcmeTestRule extends AcmeTestCase4 {
    @Test
    public void testAssertions() {
        try {
            assert false;
        } catch (AssertionError) {
            // good.
            return;
        }

        fail("Didn't throw AssertionError on assert false");
    }
}

我们的自动构建测试失败了,因为“assert false”仍然没有抛出异常。从 IDE 运行完全相同的测试通过。我们没有设置任何命令行标志来打开断言(尽管 IDE 可能在我们背后做这件事。)

顺便说一句,如果我这样做:

public class TestAcmeTestRule {
    @ClassRule
    public static final AcmeTestRule acmeTestRule = new AcmeTestRule();

    @Test
    public void testAssertions() {
        try {
            assert false;
        } catch (AssertionError) {
            // good.
            return;
        }

        fail("Didn't throw AssertionError on assert false");
    }
}

结果测试现在在 IDE 中也失败了。我所做的只是将规则从抽象类移到测试类中。

我认为这是一些奇怪的类加载问题。我的理论:断言状态只在读取字节码时使用,所以当你运行字节码时,改变值已经太晚了。

4

1 回答 1

3

(以及所有类似方法)的问题ClassLoader.setDefaultAssertionStatus是,它们对已经加载的类没有影响。从文档

此设置确定由此类加载器加载并 将来初始化 类是否默认启用或禁用断言。

因此,只要您不确保在加载所有其他类之前执行此操作(这可能容易出错),您就无法在代码中可靠地启用断言。

这在 IDE 中起作用的原因可能是 IDE 倾向于通过传递适当的命令行参数来启用断言,或者类加载的顺序可能不同。

于 2012-11-07T06:10:19.120 回答