Download as ppt, pdf, or txt
Download as ppt, pdf, or txt
You are on page 1of 16

JUnit 4

21-Apr-12

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 Dont 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 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

Use annotations instead of special method names:


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


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

@BeforeClass public static void setUpClass() throws Exception { // one-time initialization code }

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

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

@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 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 dont 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


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

@Test (timeout=10) public void greatBig() { assertTrue(program.ackerman(5, 5) > 10e12); }


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 dont want Dave to know this doesnt work") @Test public void add() { assertEquals(4, program.sum(2, 2)); }

You shouldnt 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 3s 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:

long sum(long x, long y) { return x + y; } @Test public void sum() { assertEquals(4, s.sum(2, 2)); } expected: <4> but was: <4> 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

with the following test:

gives:

This is due to your friend, autoboxing


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

You might also like