I want assertion failures throughout the code to cause my tests to fail.
I have a JUnit rule like this:
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();
}
}
}
}
And it is on a base test class like this:
public abstract class AcmeTestCase {
@ClassRule
public static final AcmeTestRule acmeTestRule = new AcmeTestRule();
}
Then to confirm that the rule itself is working, I have the following test:
public class TestAcmeTestRule extends AcmeTestCase4 {
@Test
public void testAssertions() {
try {
assert false;
} catch (AssertionError) {
// good.
return;
}
fail("Didn't throw AssertionError on assert false");
}
}
The test fails on our automated build because “assert false” still didn’t throw the exception. The exact same test passes run from the IDE. We’re not setting any command-line flag to turn on assertions (although the IDE might be doing it behind our back.)
Incidentally, if I do this:
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");
}
}
The resulting test now fails in the IDE as well. And all I did was to move the rule from the abstract class down into the test class.
I take it this is some bizarre class loading issue. My theory: assertion status is only used when reading in the bytecode, so by the time you’re running the bytecode, it’s too late to change the value.
The problem with
ClassLoader.setDefaultAssertionStatus(and all the similar methods) is, that they have no effect on classes which are already loaded. From the documentationSo you can’t reliably enable assertions in the code as long as you don’t make sure that this is executed before all other classes are loaded (which is probably error prone).
The reason why this is working in the IDE is probably that IDEs tend to enable assertions by passing the appropriate command-line parameter, or that perhaps the order of class loading is different.