java simple unit testing with JUnit tutorial

in short, JUnit is a unit testing framework for java, it is used for testing parts of your code for errors and bugs early in the development process, this will make your program and code more reliable. unit-testing is commonly used for any larg scale project and will probably be used by most companies you will work for. so being familiar with unit testing is a must for programmers.

but don’t worry it’s not very hard to learn, you just need to create some boilerplate code and write test methods that get an input and are sposed to get an expected output sometimes it’s as easy as checking if a == b.

JUnit wiki
for this tut, we will be using the Eclipse IDE but I will include tuts for other ides (like NetBeans and IntelliJ).

I will cover JUnit 4 and then JUnit 5

Download and Install JUnit

first get the JUnit 4 jar , it also has the maven dependencies in case your using maven.

eclipse has JUnit 5 jupiter out of the box (from Oxygen a few years ago) for me it came out of the box.
IntelliJ  also supports JUnit 5 jupiter last time I checked, I suggest and will also teach how to use both.
also I suggest you use eclipse, even if you dont usually use it, its alwayse good to have experience with diffrent tolls.

hers a nother JUnit setup tut

now I will show you how to include the JUnit 4 to an eclipse project:
1)in the project root create a file called jars:

2) drag and drop junit4.jar to the jars folder in your project:

3)right click junit4.jar, hover Build path and then select add to build path:

and thats it you can use junit4 in this project.

lets make a simple test

first we will use junit 4 then we will use 5.
we will create a very simple class to test, its name will be MessageUtil, all it does is print a message to the console.
here is the class to test code:

public class MessageUtil {

	   private String message;

	   //Constructor
	   //@param message to be printed
	   public MessageUtil(String message2){
	      this.message = message2;
	   }
	      
	   // prints the message
	   public String printMessage(){
	      System.out.println(message);
	      return message;
	   }   
	} 

once you add this code to eclipse, we can create a test.

all this class does is get a string and print it with the method printMessage, if you don’t understand this code, maybe you shod go over the basic syntax again.

right click the file.go to new and select junit test case:

in the window popup select junit4 and give it the name “MessageUtilTestJunit4” and click finish:

this will generate this file:

change it to this code and click run(click run when your on the test file not on main):

package main;

import static org.junit.Assert.*;

import org.junit.Test;

public class MessageUtilTestJunit4 {

	String message = "Hello World";	
	MessageUtil messageUtil = new MessageUtil(message);

	@Test
	public void testPrintMessage() {
		 assertEquals(message,messageUtil.printMessage());
		  
	}

}

lets explain the code.
first thing we do is to create a test message, and init the class we want to test.

after that we create a method testPrintMessage, to test the print messge method, what we want to test that if it returns the messge the class got.

before the method we add @Test its called “test fixture“, this will mark the method as a test case.

inside the method, we use assertEquals, it’s a static method of JUnit, it gets two objects as its argument and returns true if they are equal.

assertEquals(1,1) is the equivelent of if(1==1){return true;}else{return false;}.

if both values in that assertEquals gets are not equal you will see the green bar turns red and a field test.

in our example this might not say much but in more complex project checking test cases can save a lot of time.

test calculator program example

lets run test on a simple calculator class that will probably will be used as a part of a calculator program.

i want to show you another super simple example on when and how to use unit tests.

here is the class:

package main;

public class calc {

	public int plus(int x,int y) {return x+y;}//end plus
	public int minus(int x,int y) {return x-y;}//end minus
	public int multiply(int x,int y) {return x*y;}//end multiply
	public int divide(int x,int y) {return x/y;}//end divide
	
}

and then we will create a class to test it with different cases:

package main;

import static org.junit.Assert.*;

import org.junit.Test;

public class calcTest {

	calc c= new calc();
	
	@Test
	public void testPlus() {
		assertEquals(c.plus(1, 1),2);
	}
	

	@Test
	public void testMinus() {
		assertEquals(c.minus(1, 1),0);
	}
	
	@Test
	public void testmultiply() {
		assertEquals(c.multiply(1, 1),1);
	}
	
	@Test
	public void testDivide1() {
		assertEquals(c.divide(10, 5),2);
	}
	
	@Test
	public void testDivide2() {
		assertEquals(c.divide(1, 0),0);
	}

}

basically what we do here is create a test case for each method of the calc class, we use assertEquals to check the returned int of the method we test against the expected result, for example c.plus(1,1) is 1+1 so the expected return is 2.

if you notice divide has two tests, one of them is a test if you can divide by 0, most users wont try it,but as it is now,the program allowes to do so, while its expected of the programmers to know better and not let this happen.

lets run the test and see what happens:

yay! our first test failure and its an “arithmetic error divide by 0”.

how can we fix this?
the simplest way is to check if the y in the divide method equals 0 return 0 (its much better then having the program crush with an arithmetic error of all things.

package main;

public class calc {

	public int plus(int x,int y) {return x+y;}//end plus
	public int minus(int x,int y) {return x-y;}//end minus
	public int multiply(int x,int y) {return x*y;}//end multiply
	public int divide(int x,int y) 
	{
		if(y==0) {return 0;}
		return x/y;
		
	}//end divide
	
}

I promise you now a “real world” project wont be that easy to fix. but I wanted to show you a simple case to get you into this.

testing a computer science student assignment automatically with JUnit

you can also use unit testing to test assignments automatically(usually computer science assignments).

you give the student a class with empty methods or with partial code, each method is supposed to return an expected value(which we can test).
lets show you a very minimal example a small assignment:

package main;

public class studentAssingment {

	public boolean task_1() 
	{
		int a = 1;
		int b = 3;
		//check if a is bigger then b
		
		return true;
		
	}//end task 1
	
	public String[] task_2() 
	{
		String s = "item1,item2,item3";
		String[] ret;
		//convert s to a string array

		return ret;
		
	}
	
	
	
}

in the first task you need to check if a is bigger then be, if it is return true, else return false.
in the second task you need to convert a string to a string array.
ill show you the solved version later, lets create the test first.

I will show you how to use assert equals to check for an expected Boolean result and then for an expected array.
technically you can test for even more stuff, expected attribute value, console log etc (i will try to show you these later.
for now hers the automatic test for our assignment:

package main;

import static org.junit.Assert.assertEquals;

import java.util.Arrays;

import org.junit.Test;

public class studentAssingmentTest {

	studentAssingment sa = new studentAssingment();
	
	@Test
	public void task_1Test() {
		assertEquals(sa.task_1(),false);
	}
	
	@Test
	public void task_2Test() {
		String[] expectedr = new String[] {"item1","item2","item3"};
		boolean is_equalr = Arrays.equals(sa.task_2(),expectedr );
		assertEquals(is_equalr,true);
	}
	
	

}

in the first task test we just check if it equals to false as that’s what were expecting, that a is not bigger than be so task 1 shod return false.
the second task test has a few more lines, our goal is to test if two arrays are equal, the one we get from task 2 and our expected array called “expectedr” we use Arrays. equals a handy java core util method that gets two arrays and returns true if they are equal, we put the result on a boolean var called “is_equalr” (short for is arrays equal).
then we simply compare is_equalr to true, we expect it to be true as we expect both arrays to be equal.

the student solves the assignment like this (a good teacher will show his students how to solve assignments like this with a mock example,as its probably the first time in their lives they do something like this):

package main;

public class studentAssingment {

	public boolean task_1() 
	{
		int a = 1;
		int b = 3;
		//check if a is bigger then b
		//solved:
		return a>b;
		
	}//end task 1
	
	public String[] task_2() 
	{
		String s = "item1,item2,item3";
		String[] ret;
		//convert s to a string array
		//solved:
		ret = s.split(",");
		return ret;
		
	}
	
	
	
}

thats the correct solution lets pretend we got it from the student, usually there can be automatic software that run test on files student submitted in bulk (or a diffrent method) for our perpouse we will just drop the students file in our project and run the test that will test the assignment class:

and it passed both tests.
if the student would have made a mistake or a wrong return value, the test would have failed.
the student cant cheat he doesn’t have the test file (with the “answers”) if he tries to cheat and gets caught…I don’t envy that student.
sometimes universities will give the students jars with the tests so they can test the assignment themselves 99% don’t know how to decompile jars so its safe.
if you want to try and write these in an automated system I advise you to try repl.it its free and easy to use.

Annotations in JUnit 4 and 5

remember that @Test we put before each test method, thats an annotation.
its meta data add to the code to add readability and some add functionality.

@Test: tells junit the method is a test and shod be executed as such.

@Before: the method you attach this annotation will run before every test.

@After: same as before but the method will run after every test.

@BeforeClass/@AfterClass : the same as before and after but run once at the end or start of a class, for example BeforeClass will run the method befor the test class is executed.

@Ignore : skip this test. useful when you don’t want to run certain tests.

there are a few changes in JUnit5:

@BeforeClass is @BeforeAll, @AfterClass is @AfterAll, @Before/@After is @BeforeEach/@AfterEach,
@Ignore is @Disabled.

lets show all of this in a very simple example we have AnnotTester class with two attributes, an int called counter and a string ArrayList called slist:

package main;

import java.util.ArrayList;

public class AnnotTester {

	public int counter;
	public ArrayList<String> slist;	
}



thats the junit 4 test for this class:

package main;

import static org.junit.Assert.assertEquals;

import java.util.ArrayList;

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;

public class AnnotTesterTest4 {

	public static AnnotTester at;
	
	@BeforeClass
	public static void before_everything() 
	{
		System.out.println("--before all test--");
		at = new AnnotTester();
		at.counter=0;
		at.slist = new ArrayList<String>();
	}
	
	@AfterClass 
	public static void after_everything() 
	{
		System.out.println("--after all test--");
		at.counter=0;
		at.slist.clear();
	}
	
	@Ignore 
	public void ignor_me() {
		System.out.println("--will not run--");
	}
	
	@Before 
	public void befor_every_test() {
		System.out.println("--befor test--");
		at.counter=0;
	}
	
	@After 
	public void after_every_test() {
		System.out.println("--after test--");
		at.slist = new ArrayList<String>();
	}
	
	@Test 
	public void test1() {
		System.out.println("list size:"+at.slist.size());
		assertEquals(at.slist.size(),0);
	}
	
	@Test 
	public void test2() {
		at.counter++;
		System.out.println("counter:"+at.counter);
		assertEquals(at.counter,1);
	}
	
	

}

this is a very simple test or a mock test to show you how to use all the Annotations.
before everything runs we print “–before all test–” initialize the AnnotTester object at, set counter to 0 and init the array list too, we do the same for the after_everything.

ignor_me will not run as we use the @Ignore annotation.

befor_every_test prints “–befor test–” and sets the counter to 0.
after_every_test prints “–after test–” and reinits athe array list (for no reason, just wanted to do somthing diffrent for the @after example).
test 1 and two are just random tests to make sure everything works (while not testing anything really i just wanted to show you how Annotations work with a mock example.

heres the same code but for JUnit5 jupiter:

package main;

import static org.junit.Assert.assertEquals;

import java.util.ArrayList;

import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;

class AnnotTesterTest5 {

	public static AnnotTester at;
	
	@BeforeAll
	public static void before_everything() 
	{
		System.out.println("--before all test--");
		at = new AnnotTester();
		at.counter=0;
		at.slist = new ArrayList<String>();
	}
	
	@AfterAll 
	public static void after_everything() 
	{
		System.out.println("--after all test--");
		at.counter=0;
		at.slist.clear();
	}
	
	@Disabled 
	public void ignor_me() {
		System.out.println("--will not run--");
	}
	
	@BeforeEach 
	public void befor_every_test() {
		System.out.println("--befor test--");
		at.counter=0;
	}
	
	@AfterEach 
	public void after_every_test() {
		System.out.println("--after test--");
		at.slist = new ArrayList<String>();
	}
	
	@Test 
	public void test1() {
		System.out.println("list size:"+at.slist.size());
		assertEquals(at.slist.size(),0);
	}
	
	@Test 
	public void test2() {
		at.counter++;
		System.out.println("counter:"+at.counter);
		assertEquals(at.counter,1);
	}

}

nothing but the annotation names have changed. it practically the same code.
with what you have learned up to now alone you can make many kinds of tests.

test console output

while this is not a common case, it is possible to test console output, I could have left it out, but i do want to show you how to do this.

this will be the class we will be testing, two methods that return void and print to console:

package main;

public class console_loger {

	public void say_bla() {System.out.print("bla");}
	
	public void multiline_print() 
	{
		int[] nums = new int[] {5,4,3,7,8,11};
		for(int n :nums)
		{
	       System.out.println(n);
		}
	}
}

and this is the test for that class (dont be scared of the code most of it is copy paste boiler plate code):

package main;


import static org.junit.Assert.assertEquals;

import java.io.ByteArrayOutputStream;
import java.io.PrintStream;

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

public class console_logerTest {

	
	private final ByteArrayOutputStream oc = new ByteArrayOutputStream();
	private final ByteArrayOutputStream errContent = new ByteArrayOutputStream();
	private final PrintStream originalOut = System.out;
	private final PrintStream originalErr = System.err;
	
	console_loger cl = new console_loger();
	@Before
	public void setUpStreams() {
	    System.setOut(new PrintStream(oc));
	    System.setErr(new PrintStream(errContent));
	    oc.reset();
	}

	@After
	public void restoreStreams() {
	    System.setOut(originalOut);
	    System.setErr(originalErr);
	}
	
	@Test
	public void blatest() {
		cl.say_bla();
		assertEquals("bla",oc.toString());
	}
	
	@Test
	public void multiline_printtest() {
		cl.multiline_print();
		String text = oc.toString();
		text = text.replace("\n", ",").replace("\r", "");
		assertEquals("5,4,3,7,8,11,",text);
	}
	
	

}

we will break most of it, for now I want to show you the boilerplate code you will need to copy-paste if you want to test console output:

	
	private final ByteArrayOutputStream oc = new ByteArrayOutputStream();
	private final ByteArrayOutputStream errContent = new ByteArrayOutputStream();
	private final PrintStream originalOut = System.out;
	private final PrintStream originalErr = System.err;
	

	@Before
	public void setUpStreams() {
	    System.setOut(new PrintStream(oc));
	    System.setErr(new PrintStream(errContent));
	    oc.reset();
	}

	@After
	public void restoreStreams() {
	    System.setOut(originalOut);
	    System.setErr(originalErr);
	}

once you put this code inside your test class you can test console output easily.

lets have a look at the blatest test, what we do there is run the bla method so it will print to the console.
and then we use assertEquals with “bla” string as the expected value, and oc.toString() on the other side.

oc.toString() is what gets the current console output as a string.

the console output will be cleared before the next test using oc.reset(); in the before method.
in multiline_printtest we put the console output on a string called text, and then we remove all of the line break so we can test the output against a string that doesn’t have line breaks. we use the string replace method for that twice.
and that’s it that’s how you test the console output, its not done often but just in case now you know how to do it.

Leave a comment