简体   繁体   中英

JUnit: Enable assertions in class under test

I've been bit a few times by Java assert statements that didn't fail in the JUnit test suite because assertions weren't enabled in JUnit's JVM instance. To be clear, these are "black box" assertions inside implementations (checking invariants, etc) not the assertions defined by the JUnit tests themselves. Of course, I'd like to catch any such assertion failures in the test suite.

The obvious solution is to be really careful to use -enableassertions whenever I run JUnit, but I'd prefer a more robust solution. One alternative is to add the following test to every test class:

  @Test(expected=AssertionError.class)
  public void testAssertionsEnabled() {
    assert(false);
  }

Is there a more automatic way to accomplish this? A system-wide configuration option to JUnit? A dynamic call I could put in the setUp() method?

In Eclipse you can go to WindowsPreferencesJavaJUnit , which has an option to add -ea everytime a new launch configuration is created. It adds the -ea option to the Debug Configuration as well.

The full text next to a check box is

Add '-ea' to VM arguments when creating a new JUnit launch configuration

I propose three possible (simple?) fixes which work for me after a quick test (but you might need to check the side effects of using a static-initializer-block)

1.) Add a static-initializer block to those testcases which rely on assertions being enabled

import ....
public class TestXX....
...
    static {
        ClassLoader.getSystemClassLoader().setDefaultAssertionStatus(true);
    }
   ...
   @Test(expected=AssertionError.class)
   ...
...

2.) Create a base-class which all of your test-classes extend which need assertions enabled

public class AssertionBaseTest {
    static {
        //static block gets inherited too
        ClassLoader.getSystemClassLoader().setDefaultAssertionStatus(true);
    }
}

3.) Create a test suite which runs all your test

import org.junit.runner.RunWith;
import org.junit.runners.Suite;

@RunWith(Suite.class)
@Suite.SuiteClasses({
    //list of comma-separated classes
    /*Foo.class,
    Bar.class*/
})
public class AssertionTestSuite {
    static {
        //should run before the test classes are loaded
        ClassLoader.getSystemClassLoader().setDefaultAssertionStatus(true);
    }
    public static void main(String args[]) {
        org.junit.runner.JUnitCore.main("AssertionTestSuite");
    }
}

Alternatively, you may compile your code such that assertions cannot be turned off. Under Java 6, you may use "fa.jar – Force assertion check even when not enabled" , a small hack of mine.

As a friend of mine says... why take the time to write an assert if you are just going to turn it off?

Given that logic all assert statements should become:

if(!(....))
{
    // or some other appropriate RuntimeException subclass
    throw new IllegalArgumentException("........."); 
}

To answer your question a way you probably want :-)

import org.junit.BeforeClass;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;


@RunWith(Suite.class)
@Suite.SuiteClasses({
        FooTest.class,
        BarTest.class
        })
public class TestSuite
{
    @BeforeClass
    public static void oneTimeSetUp()
    {
        ClassLoader.getSystemClassLoader().setDefaultAssertionStatus(true);
    }
}

Then run the test suite rather than each test. This should (works in my testing, but I did not read the internals of the JUnit framework code) result in the assertion status being set before any of the test classes are loaded.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM