JUnit Testing Tips - Constructor is Called Before Executing Test Methods

Even though almost all Java programmers either use JUnit or TestNG for there unit testing need along with some mock object generation libraries e.g. Mockito, but not everyone spends time and effort to learn subtle details of these testing libraries, at least not in proportion of any popular framework likeSpring or Hibernate. In this blog post, I am sharing one of such detail, which has puzzled me a couple of years ago. At that time, though I had been using JUnit for a significant time, I wasn't aware that code written inside the constructor of Test class is executed before each test method.  This behavior of JUnit has caused, some of my test to failed and putting hours of investigation in my code, without realizing that this is happening because of JUnit is initializing the object by calling constructor before executing test method annotated with @Test annotation.

I had the following code to test my vending machine implementation as a coding exercise. If you look at closely, I have initialized vending machine in the class body, which is executed as part of the constructor.

I was assuming one instance of the vending machine is shared between all test methods, as I was not using @Before and @After, JUnit 4 annotation for setup() and tearDown().

In the first test, one item from Inventory is consumed and in second test another item, but when you assert count of items based upon the previous test, it will fail, because you are testing a different vending machine instance, which has different inventory.

So always, remember that JUnit calls the constructor of test class before executing the test method. You can verify it by putting a System.out.println message in the constructor itself. Btw, if you are just starting with JUnit or have used it quite a long ago, then I suggest you to first refresh your concepts by going throughJUnit and Mockito Crash Course.

JUnit Testing Tips - Constructor is Called Before Executing Test Methods

JUnit has already come a long way with enhancements in JUnit 4.0 and JUnit 5.0, the latest release of JUnit.

Code Written in Constructor is Executed before each Test Method

JUnit Tips for Java Programmers Here is a code example of a JUnit test, which will demonstrate this point.  In our JUnit test class VendingMachineTest we have two test methods, buyDrinkWithExactAmount() and buyDrinkWithExactAmount(), and we are printing a message from a constructor.

In the output section, you can see that message from constructor has appeared two times, one for each test case. This proves that the constructor of JUnit test class is executed before each test method.

import java.util.List;

import org.junit.Test;

import static org.junit.Assert.;

/**

*

* @author Javin

*/

public class VendingMachineTest {

private VendingMachine machine = new VendingMachine();

public VendingMachineTest(){

System.out.println("JUnit Framework calls Constructor of test class before executing test methods");

}

@Test

public void buyDrinkWithExactAmount(){

int price = machine.choose(Item.COKE);

assertEquals(70, price);

assertEquals(Item.COKE, machine.currentItem);

machine.insert(Coin.QUARTER);

machine.insert(Coin.QUARTER);

machine.insert(Coin.DIME);

machine.insert(Coin.DIME);

assertEquals(70, machine.balance);

assertEquals(7, (int) machine.coinInvertory.getCount(Coin.DIME));

assertEquals(7, (int) machine.coinInvertory.getCount(Coin.QUARTER));

Item i = machine.dispense();

assertEquals(Item.COKE, i);

assertEquals(4, (int) machine.itemInvertory.getCount(i));

List change = machine.getChange();

assertTrue(change.isEmpty());

}

@Test

public void buyDrinkWithMoreAmount(){

int price = machine.choose(Item.SPRITE);

assertEquals(90, price);

assertEquals(Item.SPRITE, machine.currentItem);

machine.insert(Coin.QUARTER);

machine.insert(Coin.QUARTER);

machine.insert(Coin.QUARTER);

machine.insert(Coin.QUARTER);

assertEquals(100, machine.balance);

assertEquals(9, (int) machine.coinInvertory.getCount(Coin.QUARTER));

Item i = machine.dispense();

assertEquals(Item.SPRITE, i);

assertEquals(4, machine.itemInvertory.getCount(i));

//this was failing, because by default VM initialize inventory with 5 items

assertEquals(4, machine.itemInvertory.getCount(Item.COKE));

List change = machine.getChange();

assertEquals(1, change.size());

assertEquals(Coin.DIME, change.get(0));

assertEquals(4, machine.coinInvertory.getCount(Coin.DIME));

}

Output:

Testsuite: test.VendingMachineTest

JUnit Framework calls Constructor of test class before executing test methods

JUnit Framework calls Constructor of test class before executing test methods

Tests run: 2, Failures: 1, Errors: 0, Time elapsed: 1.421 sec

Result

------------- ---------------- ---------------

Testcase: buyDrinkWithMoreAmount(test.VendingMachineTest):      FAILED

expected:<4> but was:<5>

junit.framework.AssertionFailedError: expected:<4> but was:<5>

at test.VendingMachineTest.buyDrinkWithMoreAmount(VendingMachineTest.java:63)

That's all guys. I feel this is a worth knowing detail if you are using JUnit for writing unit test in your Java project. Sometimes, we have a bug in unit test itself, but we suspect our code. So it must for all Java developers to know the nitty-gritty of JUnit testing framework as well.

Further Learning

Unit Testing In Java With JUnit

JUnit and Mockito Crash Course

Learn Unit Testing with JUnit & Mockito in 30 Steps

Thanks for reading this article so far. If you like this JUnit tips then please share with your friends and colleagues. If you have any questions or feedback then please drop a note.