我想在整个代码中断言失败,以使我的测试失败。
我有这样的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");
}
}
测试在我们的自动化构建中失败,因为"断言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中也失败了。我所做的就是将规则从抽象类移至测试类。
我认为这是一些奇怪的班级加载问题。我的理论:仅在bytecode中阅读时才使用断言状态,因此,到您运行字节码时,更改值为时已晚。
ClassLoader.setDefaultAssertionStatus
的问题(以及所有类似的方法)是,它们对已经加载的类没有影响。从文档
此设置确定 Future 在此类加载程序加载和初始化的中是否加载的类。P>
因此,只要您不确定在加载所有其他类之前,您就无法可靠地启用代码中的断言(这可能是错误的)。
在IDE中起作用的原因可能是IDE倾向于通过适当的命令行参数来启用断言,或者类别加载的顺序可能不同。