My Java World

A blog about Java technology.

  • Categories

  • Archives

  • Flickr Photos

    Segundo dia (second day)

    Segundo dia (second day)

    Segundo dia (second day)

    More Photos

JUnit 4 + Hamcrest. Let’s create unit testing for our Java applications

Posted by jrjuniorsp on November 8, 2007

In this topic we are going to see how to create unit testing using JUnit 4 + Hamcrest.

To work with these frameworks, you must be using Java 5.

What is Unit Testing?

Unit Testing are piece of code that tests others pieces of code, also known as UNIT.

You application is split in many units. An unit could be a single method.

Unit Testing has the goal to test the application code and make sure all units are working properly. If you do any change or enhancement, the Unit Testing can ensure the original code behavior keeping running properly.

Also, Unit testing can ensure your code keeps correct after a refactoring. About this issue, Martin Fowler says:
Again, you don’t want to be surprised when the code breaks because somebody has changed it. One great thing JUnit-style tests give you is the ability to run them and see if you’ve broken anything. It’s no big deal if you aren’t changing anything, but if you’re adding features or fixing bugs there’s always the chance you’ll break something. As you get better at your tests, you become more confident about the things you can change. As a result, you can get some high reliability rates.

Unit Testing is the principal feature for TDD (Test Driven-Development).

As you can see, Unit Testing is an important behavior for any Java Application and in this topic we are going to see how to work with Unit Testing in Java Applications.

What do these frameworks do?

All of this frameworks are used to make unit testing in Java applications.

JUnit: JUnit is a unit testing framework for the Java programming language. Created by Kent Beck and Erich Gamma, JUnit is one of, and arguably the most successful of, the xUnit family of frameworks that originated with Kent Beck’s SUnit. JUnit has spawned its own ecosystem of JUnit extensions.

Hamcrest: Provides a library of matcher objects (also known as constraints or predicates) allowing ‘match’ rules to be defined declaratively, to be used in other frameworks. Typical scenarios include testing frameworks, mocking libraries and UI validation rules.

Understanding and Creating our first example using JUnit 4

JUnit 4 requires Java 5. Also, you have to download the latest JUnit version here.

Many IDEs such as Eclipse, Netbeans, RAD, IntelIDEA, etc, have support for JUnit internally, but you are able to run JUnit out of these IDEs as well.

Our first example, is a really simple example. You will need the junit-4.4.jar file in your application classpath.

Let’s create a simple class called Math. This class has a method called sum that receives two parameters and make a sum between these two values. The sum of the values are returned by the method.

package junit4example;

public class Math {
	public int sum(int value1, int value2) {
		return value1 + value2;
	}
}

The code above is a simple class with a simple method.

The behavior of this method should be simple, receives two parameters and sum them.

Now, let’s create our first JUnit class using JUnit4. The class is below:

package junit4example;

import static junit.framework.Assert.*;

import org.junit.Before;
import org.junit.Test;

public class TestMath {

	//Attribute
	Math math;

	@Before
	public void setUp() throws Exception {
		math = new Math();
	}
	@Test
	public void testSumSuccessfully() {
		assertTrue(math.sum(1, 1) == 2);
	}
}

The class above is a simple class to the our Math class.

Firstly, you can see the name of the class. It starts with the word “Test”+Name of the class. In JUnit4 it is not required, but it is common the people use this nomenclature. The class doesn’t extend none class. In JUnit3 we had to extend the TestCase class.

You can see the method setUp() and an annotation @Before. It means this method will run before the methods with annotation @Test. Usually method with @Before annotation, are method to declare objects and prepare them to the tests.

Now, look at the method testSumSuccessfully(). It has the annotation @Test, in other words, it means this method will be tested. Also look at its nomenclature. It starts with the word “test”, but like the class, in JUnit4 it is not required.

The body of this method is simple, we are using a method called assertTrue(). This method expects true in the expression. If it is false, an assertionException is thrown.

In our simple example, we expect the method SUM returns 2 when are sent it the parameters 1 and 1.

Running this class (for instance, using Eclipse), a JUnit perspective will be open and a ProgressBar will appear. Green bar success, red bar fail. In our example, we will get GREEN BAR.

junit1.jpg

Supposing our method into Math class is wrong, like the example below:

package junit4example;

public class Math {
	public int sum(int value1, int value2) {
		return value1 + value2 + 1;
	}
}

When we will run the JUnit class, it will return error (RED BAR), because the method is returning 3 rather than 2.

junit2.jpg

You are able to create many tests methods inside a JUnit class. By the way, it is good have many kind of tests inside the same unit.

	 @Test
	public void testSumSuccessfully() {
		assertTrue(math.sum(1, 1) == 2);
		assertTrue(math.sum(5, 5) == 10);
		assertTrue(math.sum(10, 10) == 20);
	}
	@Test
	public void testSumError() {
		assertFalse(math.sum(1, 1) == 3);
	}

The example above we have two methods (both with @Test annotation) and in the first method, we have three tests.

Look at the second method and you will see another method from JUnit, assertFalse(). Different than assertTrue(), assertFalse expects the expression returns false.

We have many others methods for JUnit, such as: assertEquals(),assertSame(),assertNull(),assertNotSame(),assertNotNull(),etc.

You are able to test Exception too. Changing our example, supposing our sum() class, cannot receive a value greater than 100. If it receives, it must thrown an exception. Like code below:

package junit4example;

public class Math {
	public int sum(int value1, int value2) {
		if (value1 >= 100) {
			throw new IllegalArgumentException(“The number must be lesser than 100″);
		}
		return value1 + value2;
	}
}

Now, let’s add the following method into JUnit class.

	 @Test(expected=IllegalArgumentException.class)
	public void testSumWithException() {
		math.sum(101, 1);
	}

You can see a attribute called “expected” into @Test annotation. In this way, you can also test any Exception using JUnit 4.

Hamcrest

Hamcrest was originally created for constraint feature from JMock 1. Today it is an independent project and can be used in many frameworks, such as JUnit, TestNGL, JMock, EasyMock.

Actually, JUnit 4.4 integrates such features from Hamcrest, however unfortunately if you want to use ALL features, you have to download a separate package.

Hamcrest allows you to create your expression easier. Let’s see the same example above, but using Hamcrest instead.

Y ou will need the hamcrest-all-1.1.jar file to use hamcrest.

package junit4example;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;

import org.junit.Before;
import org.junit.Test;

public class TestMathHamcrest {
	private Math math;
	@Before
	public void setUp() throws Exception {
		math = new Math();
	}

	@Test
	public void testSumSuccessfully() {
		assertThat(math.sum(1, 1),equalTo(2));
	}	

	@Test
	public void testSumError() {
		assertThat(math.sum(1, 1), not(equalTo(3)));
	}

}

The code above has the same behavior than the code using only JUnit4, except by the fact we are using Hamcrest constraints instead.

Look at the method assertThat(). This methods receives a Matcher as parameters. Matcher are easier to understand than expression. Also, you are able to create your own Matcher.

Instruction about creating your own Matcher and all matcher available can be read in the hamcrest’s official tutorial.

A real example where Hamcrest is easier than Expression in JUnit4.

Supposing the Math class has a method which returns a java.util.List of operations. Code example:

	public List<String> getListOperations() {
		List<String> list = new LinkedList<String>();
		list.add(“sum”);
		list.add(“subtract”);
		list.add(“multiplication”);
		list.add(“division”);
		return list;
	}

How could we test this method using JUnit 4?

Well, we could for instance test element by element, anything like this:

	@Test
	public void testGetListSuccess() {
		//–My object
		List<String> list = new LinkedList<String>();
		list.add(“sum”);
		list.add(“subtract”);
		list.add(“multiplication”);
		list.add(“division”);
		//–Getting object from method
		List<String> originalList = math.getListOperations();
		int count = 0;
		for (String operation : originalList) {
			assertEquals(operation, list.get(count));//Testing here
			count++;
		}
	}

Ugly code, isn’t it?

Below following the code using Hamcrest (assertThat):

	@Test
	public void testGetListSuccess() {
		assertThat(math.getListOperations(), hasItems(“sum”,“subtract”,“multiplication”,“division”));
	}

The code above has the same behavior from previous code but it is shorter and much easier to understand :)

Hamcrest increases the ability to use JUnit4 and I am pretty sure you will give more productivity working with this framework.

You can download the example used in this topic clicking here.

I hope this topic be useful for you. On the next topic, I am going to write about MockObject, especially JMock.

See you soon. Thanks

 

 

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>