junit

JUnit Tutorial for Beginners

1. Introduction

In this post, we will discus the basics of setting up your JUnit Test cases. We’ll go step by step in creating test cases as we go along with creating our application. Before we dive into it though, why do we even need to create test cases? Isn’t it enough to just create the implementation since it’s what we are delivering anyway?

Although the actual implementation is part of the package, the JUnit Test case is a bullet proof evidence that what we wrote is what the actual requirements or functions will do. It is the concrete basis of a specific unit/function which does what it needs to do.
 

 
Knowing the impact in the stability of the application. The JUnit Test cases defines the stability of an application even after several extensions to it. If done correctly, it guarantees that the extension made to the system will not break the entire system as a whole. How does it prevent it? If the developers write clean unit and integration tests, it will report any side effects via the reporting plugins that the application uses.

Regression and Integration Testing. The effort of testing is relative to the applications size and changes done. By creating JUnit Test cases, regression and integration tests can be automated and can definitely save time and effort.

Overall, creating JUnit Test cases are definitely a must do by all developers, sadly there are still who don’t uses it’s power to it’s full extent and some just doesn’t do it. It’s sometimes a shame to think that one of the purest way of developing bullet proof code is not done by the developers. It can be because of the lack of training, experience or just pressure of not delivering the actual value (which is a problem within itself since although not part of the implementation, it’s a most valuable component of your code) but thats not an excuse especially that software are now globally taking over most of the major systems (medical, auto, planes, buildings) in the world. The stability of these systems rely on the stability of the unit test cases.

So as a precursor to being a skilled full blown developer that loves to do unit test, let’s dive into some of the beginners guide into doing it.

2. Tools

For this example, I’ll be using Java as the platform, Eclipse as the IDE, and Maven as the project management tool. If you’re not yet familiar with these tools, please visit the Java, Eclipse IDE and Maven site.

3. Step by Step Guide

3.1 Create your project

Let’s create a project first.

Figure 1.0 New Maven Project
Figure 1.0 New Maven Project

After creating the project, you’ll be shown a project like the one below:

Figure 2.0 New Maven Project .xml
Figure 2.0 New Maven Project .xml

Make sure you include the Junit Library to your dependency list.

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.jgc.areyes.junit</groupId>
  <artifactId>junit-test-beginners-example</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  
      
  <dependencies>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.12</version>
			<scope>test</scope>
		</dependency>

	</dependencies>
	
	
</project>

3.2 Create the Service Class

Majority of the developers I know starts first with creating the implementation rather than the JUnit Test case, it isn’t a bad practice at all but wouldn’t it be more concrete if we create the JUnit Test cases first based on the design then create the implementation to pass all JUnit Test case? This is the case in the TDD, one of the most successful schemes of actual software development.

Assuming we are creating a service to manage an account. We need to introduce the following service methods:

  • Create a new Account
  • Update an Account
  • Remove an Account
  • List All Account Transactions

We have an OOP design that will handle this service and so we introduce the following classes (Class Diagram).

Figure 3.0 Class Diagram
Figure 3.0 Class Diagram

Here is the actual class that doesn’t have any implementation yet. We will create the implementation after creating the test cases for this class.

AccountServiceImpl.java

package com.areyes1.jgc.svc;

import java.util.List;

import com.areyes1.jgc.intf.AccountService;
import com.areyes1.jgc.obj.Account;
import com.areyes1.jgc.obj.Transaction;

public class AccountServiceImpl implements AccountService {
	public Account createNewAccount(Account account) {
		// TODO Auto-generated method stub
		return null;
	}

	public Account updateAccount(Account account) {
		// TODO Auto-generated method stub
		return null;
	}

	public Account removeAccount(Account account) {
		// TODO Auto-generated method stub
		return null;
	}

	public List listAllTransactions(Account account) {
		// TODO Auto-generated method stub
		return null;
	}
}

3.3 Create JUnit Test Cases

Now that we have the service placeholder, let’s create the Junit Test case for the AccountServiceImpl class. The Test cases will be the basis of your class functional aspect so you as a developer should write a solid and good test case (and not just fake it to pass).

When you create a test case, it will initially look like this:

AccountServiceImplTest.java

/**
 * 
 */
package com.areyes1.jgc.svc;

import static org.junit.Assert.*;

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

/**
 * @author alvinreyes
 *
 */
public class AccountServiceImplTest {

	/**
	 * Test method for {@link com.areyes1.jgc.svc.AccountServiceImpl#createNewAccount(com.areyes1.jgc.obj.Account)}.
	 */
	@Test
	public void testCreateNewAccount() {
		fail("Not yet implemented");
	}

	/**
	 * Test method for {@link com.areyes1.jgc.svc.AccountServiceImpl#updateAccount(com.areyes1.jgc.obj.Account)}.
	 */
	@Test
	public void testUpdateAccount() {
		fail("Not yet implemented");
	}

	/**
	 * Test method for {@link com.areyes1.jgc.svc.AccountServiceImpl#removeAccount(com.areyes1.jgc.obj.Account)}.
	 */
	@Test
	public void testRemoveAccount() {
		fail("Not yet implemented");
	}

	/**
	 * Test method for {@link com.areyes1.jgc.svc.AccountServiceImpl#listAllTransactions(com.areyes1.jgc.obj.Account)}.
	 */
	@Test
	public void testListAllTransactions() {
		fail("Not yet implemented");
	}

}

As it can be seen above, it will fail the test case if it’s not yet implemented. From here on now, it’s a matter of discipline from the developer to create concrete and solid test cases.

Observing the JUnit Test cases.

  • Using @Test to define a test method
  • Put them all on the Test package (src/test/main/)
  • Class always has a suffix of Test (AccountServiceImplTest)
  • Methods always starts with “test”.

Here’s is the modified version of the JUnit Test cases. This will now be the basis of our implementation code.

AccountServiceImplTest.java

/**
 * 
 */
package com.areyes1.jgc.svc;

import static org.junit.Assert.*;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.hamcrest.CoreMatchers.*;
import com.areyes1.jgc.obj.Account;
/**
 * @author alvinreyes
 *
 */
public class AccountServiceImplTest {

	AccountServiceImpl accountService = new AccountServiceImpl();
	
	/**
	 * Test method for {@link com.areyes1.jgc.svc.AccountServiceImpl#createNewAccount(com.areyes1.jgc.obj.Account)}.
	 */
	@Test
	public void testCreateNewAccount() {
		Account newAccount = new Account();
		newAccount.setName("Alvin Reyes");
		newAccount.setDescription("This is the description");
		
		Account newAcccountInserted = accountService.createNewAccount(newAccount);
		
		//	Check if the account has the same composition.
		assertThat(newAccount, isA(Account.class));
		assertEquals(newAccount.getName(), newAcccountInserted.getName());

	
	}

	/**
	 * Test method for {@link com.areyes1.jgc.svc.AccountServiceImpl#updateAccount(com.areyes1.jgc.obj.Account)}.
	 */
	@Test
	public void testUpdateAccount() {
		
		
		//	The old account (assumed that this came from a database or mock)
		Account oldAccount = new Account();
		oldAccount.setName("Alvin Reyes");
		oldAccount.setDescription("This is the description");
		
		String name = oldAccount.getName();
		//	Check if the account is still the same. it is expected to be different since we updated it.
		Account expectedAccountObj =  new Account();
		expectedAccountObj = accountService.updateAccount(oldAccount);
		assertThat(expectedAccountObj, isA(Account.class));
		assertNotEquals(name, expectedAccountObj.getName());
		
	}

	/**
	 * Test method for {@link com.areyes1.jgc.svc.AccountServiceImpl#removeAccount(com.areyes1.jgc.obj.Account)}.
	 */
	@Test
	public void testRemoveAccount() {
		
		//	Set up the account to be removed.
		Account toBeRemovedAccount = new Account();
		toBeRemovedAccount.setName("Alvin Reyes");
		toBeRemovedAccount.setDescription("This is the description");
		
		//	Removed the account.
		assertTrue(accountService.removeAccount(toBeRemovedAccount));
		
	}

	/**
	 * Test method for {@link com.areyes1.jgc.svc.AccountServiceImpl#listAllTransactions(com.areyes1.jgc.obj.Account)}.
	 */
	@Test
	public void testListAllTransactions() {
		
		//	 Dummy Transactions (can be mocked via mockito)
		Account account = new Account();
		account.setName("Alvin Reyes");
		
		//	Service gets all transaction
		accountService.listAllTransactions(account);
		
		//	Check if there are transactions.
		assertTrue(accountService.listAllTransactions(account).size() > 1);
		
		
	}

}

Running the test case will show the following result.

Figure 4.0 Failed Test cases
Figure 4.0 Failed Test cases

It failed cause we still have to code our implementation. Now in the implementation of our logic, our goal is make sure that these test cases succeeds!

3.4 Code the implementation

Now that the test cases are setup, we can now code our implementation. The test cases we created above will be the basis of how we will create the implementation. The goal is to pass the test cases!

package com.areyes1.jgc.svc;

import java.util.ArrayList;
import java.util.List;

import com.areyes1.jgc.intf.AccountService;
import com.areyes1.jgc.obj.Account;
import com.areyes1.jgc.obj.Transaction;

public class AccountServiceImpl implements AccountService {
	public Account createNewAccount(Account account) {
		//	Dummy Dao! Database insert here.
		//	accountDao.insert(account);
		//	Ultimately return the account with the modification.
		return account;
		
	}

	public Account updateAccount(Account account) {
		//	Dummy Dao! Database insert here.
		//	accountDao.update(account);
		//	Ultimately return the account with the modification.
		account.setName("Alvin Reyes: New Name");
		return account;
	}

	public boolean removeAccount(Account account) {
		//	Dummy Dao! Database insert here.
		//	accountDao.delete(account);
		//	Ultimately return the account with the modification.
		//	if exception occurs, return false.
		return true;	
	}

	public List listAllTransactions(Account account) {
		// accountDao.loadAllTransactions(account);
		List listOfAllTransactions = new ArrayList();
		listOfAllTransactions.add(new Transaction());
		listOfAllTransactions.add(new Transaction());
		listOfAllTransactions.add(new Transaction());
		account.setTransactions(listOfAllTransactions);
		
		return listOfAllTransactions;
	}
}

Running the test case will show the following result.

Figure 5.0 Passed Test case
Figure 5.0 Passed Test case

3.5 Run your maven

Run your maven to see results.

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running com.areyes1.jgc.svc.AccountServiceImplTest
Tests run: 4, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.051 sec

Results :

Tests run: 4, Failures: 0, Errors: 0, Skipped: 0

[INFO] 
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ junit-test-beginners-example ---
[INFO] Building jar: /Users/alvinreyes/EclipseProjects/Java/junit-test-beginners-example/target/junit-test-beginners-example-0.0.1-SNAPSHOT.jar
[INFO] 
[INFO] --- maven-install-plugin:2.4:install (default-install) @ junit-test-beginners-example ---
[INFO] Installing /Users/alvinreyes/EclipseProjects/Java/junit-test-beginners-example/target/junit-test-beginners-example-0.0.1-SNAPSHOT.jar to /Users/alvinreyes/.m2/repository/com/jgc/areyes/junit/junit-test-beginners-example/0.0.1-SNAPSHOT/junit-test-beginners-example-0.0.1-SNAPSHOT.jar
[INFO] Installing /Users/alvinreyes/EclipseProjects/Java/junit-test-beginners-example/pom.xml to /Users/alvinreyes/.m2/repository/com/jgc/areyes/junit/junit-test-beginners-example/0.0.1-SNAPSHOT/junit-test-beginners-example-0.0.1-SNAPSHOT.pom
[INFO] 
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ junit-test-beginners-example ---
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 0 resource
[INFO] 
[INFO] --- maven-compiler-plugin:2.5.1:compile (default-compile) @ junit-test-beginners-example ---
[INFO] Nothing to compile - all classes are up to date
[INFO] 
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ junit-test-beginners-example ---
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 0 resource
[INFO] 
[INFO] --- maven-compiler-plugin:2.5.1:testCompile (default-testCompile) @ junit-test-beginners-example ---
[INFO] Nothing to compile - all classes are up to date
[INFO] 
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ junit-test-beginners-example ---
[INFO] Skipping execution of surefire because it has already been run for this configuration
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 9.456 s
[INFO] Finished at: 2015-10-12T16:28:01-05:00
[INFO] Final Memory: 11M/28M
[INFO] ------------------------------------------------------------------------

4. Download the Eclipse project

This was an example of JUnit Test Beginners Tutorial

Download
You can download the full source code of this example here: junit-test-beginners-example

Alvin Reyes

Alvin has an Information Technology Degree from Mapua Institute of Technology. During his studies, he was already heavily involved in a number of small to large projects where he primarily contributes by doing programming, analysis design. After graduating, he continued to do side projects on Mobile, Desktop and Web Applications.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button