JUnit 4 14-Feb-15 Comparing JUnit 3 to JUnit 4 All the old assertXXX methods are the same Most things are about equally easy JUnit 4 makes it easier to test that exceptions are thrown when they should be JUnit 4 can still run JUnit 3 tests JUnit 4 provides protection against infinite loops JUnit 4 has some additional features Migrating from JUnit 3 JUnit 4 requires Java 5 or newer Don’t extend junit.framework.TestCase; just use an ordinary class Import org.junit.* and org.junit.Assert.* Use a static import for org.junit.Assert.* Static imports replace inheritance from junit.framework.TestCase Use annotations instead of special method names: Instead of a setUp method, put @Before before some method Instead of a tearDown method, put @After before some method Instead of beginning test method names with ‘test’, put @Test before each test method Writing a JUnit test class, I Start by importing the JUnit 4 classes you need import org.junit.*; import static org.junit.Assert.*; Declare your class in the usual way public class MyProgramTest { Declare any variables you are going to use frequently, typically including an instance of the class being tested MyProgram program; int [] array; int solution; Writing a JUnit test class, II @BeforeClass public static void setUpClass() throws Exception { // one-time initialization code } If you wish, you can declare one method to be executed just once, when the class is first loaded This is for expensive setup, such as connecting to a database If you wish, you can declare one method to be executed just once, to do cleanup after all the tests have been completed @AfterClass public static void tearDownClass() throws Exception { // one-time cleanup code } Writing a JUnit test class, III @Before public void setUp() { program = new MyProgram(); array = new int[] { 1, 2, 3, 4, 5 }; } You can define one or more methods to be executed before each test; typically such methods initialize values, so that each test starts with a fresh set You can define one or more methods to be executed after each test; typically such methods release resources, such as files @After public void tearDown() { } @Before and @After methods You can have as many @Before and @After methods as you want Be warned: You don’t know in what order they will execute You can inherit @Before and @After methods from a superclass; execution is as follows: Execute the @Before methods in the superclass Execute the @Before methods in this class Execute a @Test method in this class Execute the @After methods in this class Execute the @After methods in the superclass Writing a JUnit test class, IV A test method is annotated with @Test, takes no parameters, and returns no result All the usual assertXXX methods can be used @Test public void sum() { assertEquals(15, program.sum(array)); assertTrue(program.min(array) > 0); } Special features of @Test @Test (timeout=10) public void greatBig() { assertTrue(program.ackerman(5, 5) > 10e12); } You can limit how long a method is allowed to take This is good protection against infinite loops The time limit is specified in milliseconds The test fails if the method takes too long Some method calls should throw an exception You can specify that a particular exception is expected The test will pass if the expected exception is thrown, and fail otherwise @Test (expected=IllegalArgumentException.class) public void factorial() { program.factorial(-5); } Parameterized tests Using @RunWith(value=Parameterized.class) and a @Parameters method, you can run the same tests with multiple datasets @RunWith(value=Parameterized.class) public class FactorialTest { private long expected; private int value; @Parameters public static Collection data() { return Arrays.asList( new Object[ ][ ] { { 1, 0 }, { 1, 1 }, { 2, 2 }, { 120, 5 } }); } public FactorialTest(long expected, int value) { // constructor this.expected = expected; this.value = value; } @Test public void factorial() { assertEquals(expected, new Calculator().factorial(value)); } } Source: http://today.java.net/pub/a/today/2006/12/07/junit-reloaded.html Ignoring a test The @Ignore annotation says to not run a test @Ignore("I don’t want Dave to know this doesn’t work") @Test public void add() { assertEquals(4, program.sum(2, 2)); } You shouldn’t use @Ignore without a very good reason! Test suites As before, you can define a suite of tests @RunWith(value=Suite.class) @SuiteClasses(value={MyProgramTest.class, AnotherTest.class}) public class AllTests { … } Other stuff Failed tests now throw an AssertionError, rather than JUnit 3’s AssertionFailedError There is now a version of assertEquals for arrays of objects: assertEquals(Object[] expected, Object[] actual) Unfortunately, there is still no assertEquals for arrays of primitives JUnit 3 had an assertEquals(p, p) method for each kind of primitive p, but JUnit 4 only has an assertEquals(object, object) and depends on autoboxing A gotcha The following method: with the following test: @Test public void sum() { assertEquals(4, s.sum(2, 2)); } gives: long sum(long x, long y) { return x + y; } expected: <4> but was: <4> This is due to your friend, autoboxing assertEquals no longer exists for primitives, only for objects Hence, the 4 is autoboxed to an Integer, while sum returns a long The error message means: expected int 4, but got long 4 To make this work, change the 4 to a 4L JUnit 4 in Eclipse and NetBeans As usual, the easiest way to create a test class is just to let your IDE do it for you Here is the recommended test-driven approach Create a class containing all the “stub” methods you initially think you will need Have the IDE create the test class, with all the test methods Repeat: Write a test Make sure the test fails Write the method being tested Make sure the test now succeeds Note: When you create the test class, NetBeans in particular puts a lot of garbage lines into each test method; you can just delete these and put in your own code The End