Mar 012017

ADM

JUnit 3 vs JUnit 4 Comparison

  • 01 March 2017
  • ADM

 

JUnit 3 vs JUnit 4 Comparison - images/logos/junit.jpg

 

There is a big change between JUnit 3.x and JUnit 4.x. JUnit 4 came with a lot of new features that introduce a lots of advantages.

Feature JUnit 3.x JUnit 4.x
Compatibility JDK 1.2+ JDK 1.5+ is requered as is using annotations, generic, static import, features introduced in Java 5.
Test method annotation testXXX pattern for the method name @Test annotation
Run before the first test method in the current class is invoked None @BeforeClass annotation
Run after all the test methods in the current class have been run None @AfterClass annotation
Run before each test method override setUp() method @Before annotation
run after each test method override tearDown() method @After annotation
How to ignore a test Comment out, remove code or change the method name @Ignore annotation
Expected exception catch exception assert success @Test(expected = ArithmeticException.class) annotation
How to test timeout None @Test(timeout = 1000) annotation
static import of the assert classes None @Test(timeout = 1000) annotation

How to define a test case

Here is a practical example of the same test case in both JUnit versions. To generate the test cases for each version a simple class will be used.

package com.admfactory.junit;

public class Stock {
    private double value;
    private long quantity;

    public Stock(double value, long quantity) {
	this.value = value;
	this.quantity = quantity;
    }

    public void addStock(long q) {
	this.quantity += q;
    }

    public void removeStock(long q) throws Exception {
	if (q > this.quantity) {
	    throw new Exception("There is not enough quantity in the stock.");
	}
	this.quantity -= q;
    }

    public double getValue() {
	return this.value;
    }
    
    public double getQuantity() {
	return this.quantity;
    }

    public void setValue(double v) {
	this.value = v;
    }

    public void clear() {
	this.value = 0;
	this.quantity = 0;
    }

    public double getTotalValue() {
	return this.value * this.quantity;
    }
}

The test cases will contain unit tests for the addStock and removeStock method with different values.

JUnit 3

package com.admfactory.junit;

import junit.framework.TestCase;

public class JUnit3StockUnitTest extends TestCase {

    private Stock apples;

    public void setUp() {
	apples = new Stock(10d, 110);
    }

    public void testInitialTotalValue() {
	assertTrue(apples.getTotalValue() == 1100);
    }

    public void testAddStock() {
	apples.clear();
	apples.addStock(10);
	assertTrue(apples.getQuantity() == 10);

	apples.addStock(12);
	assertTrue(apples.getQuantity() == 22);
    }

    public void testRemoveStock() throws Exception {
	apples.clear();
	apples.addStock(10);
	assertTrue(apples.getQuantity() == 10);

	apples.removeStock(9);
	assertTrue(apples.getQuantity() == 1);
    }

    public void testException() {
	try {
	    apples.clear();
	    apples.addStock(10);

	    apples.removeStock(99);
	    fail("There is not enough in the store.");
	} catch (Exception e) {
	    assertTrue(true);
	}
    }

    public void tearDown() {
	apples.clear();
    }
}

As you can see the test cases methods starts with "test". setUp method is used to initialize the apples object and tearDown is used clear the stock.

JUnit 4

package com.admfactory.junit;

import org.junit.Test;
import static org.junit.Assert.assertTrue;

import org.junit.After;
import org.junit.Before;

public class JUnit4StockUnitTest {

    private Stock apples;
    
    @Before
    public void init() {
	apples = new Stock(10d, 110);
    }

    @Test
    public void initialTotalValue() {
	assertTrue(apples.getTotalValue() == 1100);
    }

    @Test
    public void addStock() {
	apples.clear();
	apples.addStock(10);
	assertTrue(apples.getQuantity() == 10);

	apples.addStock(12);
	assertTrue(apples.getQuantity() == 22);
    }

    @Test
    public void removeStock() throws Exception {
	apples.clear();
	apples.addStock(10);
	assertTrue(apples.getQuantity() == 10);

	apples.removeStock(9);
	assertTrue(apples.getQuantity() == 1);
    }

    @Test(expected = Exception.class)
    public void exception() throws Exception {
	apples.clear();
	apples.addStock(10);
	apples.removeStock(99);
    }

    @After
    public void clean() {
	apples.clear();
    }
    
}

Comparing the examples the test cases uses the annotation @Test, the init method uses @Before annotation, the end method uses @After annotation. Also, a big difference is how Exceptions are checked: JUnit 3.x uses try catch block and JUnit 4.x uses annotation property expected.