This Tutorial will explain When, Why, and How to use JUnit Test Fixture with simple JUnit Test Fixture Examples for your Easy Understanding of the Concept:
We will learn –
- When and why do we have the need to use Test Fixture?
- What is the approach for using it in our code for the JUnit test?
- A couple of examples to understand the term ‘Test Fixture’ parallelly cascaded with a head start on JUnit 4 lifecycle annotations like @Before, @After, @BeforeClass, @AfterClass, and @Test.
=> Check ALL JUnit Tutorials Here.
Table of Contents:
JUnit Test Fixture
When there are multiple test cases in a JUnit class, there could be a common object or objects used by all the test cases. In this case, there could be specific functions that might be common throughout all the test cases.
This doesn’t mean that the test objects have to be shared by all the test cases. The change to the object made in one test doesn’t have to be shared across all the tests as these tests are independent and may be executed in a different order as per their priority set.
The holistic understanding of the term ‘Test Fixture’ is a fixed state in a code or a set of fixed steps in a code that is used as a precondition and few other sets of steps that are used as postcondition for all the tests.
Thus, in other words, we are identifying those sets of statements that will repeat for all tests and thereby, try setting a fixed environment for our test methods to run.
The purpose of using Test Fixture is to eliminate the duplication of the common code for all the testcases.
Let’s try to understand the practical implementation of the test fixture in a JUnit test.
setUp() method
- There are tests that need the initialization of certain objects (string, integer, ArrayList, or any object for that matter). You may create a method public void setUp() in which you could declare the instance variables for the common objects. Place this setUp() method under the annotation @Before. With the @Before annotation, the framework will run the method setUp() prior to every test case execution.
- The setUp() method could also be used in case, you wish to launch a browser with a specific URL as the first step you run a test case that follows login to the application with predefined credentials.
tearDown() method
- If you have allocated external resources in a test, you should remember to free the resources too. The teardown() method could be added for the clean-up of the objects after the test case execution has been completed. In a similar fashion as the setUp() method, add a method public void teardown() under @After annotation. The JUnit framework makes sure that after each test case is run, the method under @After is surely executed. The objects used up in the test have to be set NULL in the teardown() method so that the garbage from the tests gets collected.
- Another good candidate for the clean-up of the objects is killing a browser in action after the test case is completed and releasing the memory by destroying the used objects.
- The method names setUp() and tearDown() are just a user-defined name. You may set any method name that you wish to. It is just the annotations used with the method which decide the sequence of the tests’ run.
JUnit Test Fixture Examples
In this section, we will go through two examples of the JUnit 4 test and try to understand how to use the approach of Test Fixtures in our code along with the sequence of different lifecycle annotations @Before, @After, @BeforeClass, @AfterClass, and @Test.
Of course, there will be a separate tutorial on annotations which will clarify what these are and how each of the annotations works. As of now, let’s stick to the understanding of the Test Fixture usage in the code.
JUnit 4 Test – Example 1
In this example, we will have the test fixtures in the class with three test cases. The setUp() method with @Before annotation and tearDown() method with the @After annotation.
Code:
package demo.tests; import static org.junit.Assert.*; import org.junit.After; import org.junit.Before; import org.junit.Test; public class JUnitProgram { @Before public void setUp() { System.out.println("_______________________________________________________\n"); System.out.println("This is the setUp() method that runs before each testcase"); } @Test public void test_JUnit1() { System.out.println("This is the testcase test_JUnit1() in this class"); } @Test public void test_JUnit2() { System.out.println("This is the testcase test_JUnit2() in this class"); } @Test public void test_JUnit3() { System.out.println("This is the testcase test_JUnit3() in this class"); } @After public void tearDown() { System.out.println("This is the tearDown() method that runs after each testcase"); System.out.println("_______________________________________________________\n"); } }
The resultant console window will be as shown below:
The console window makes it obvious that before every test run, the setUp() method executes, and after each test completes, the tearDown() method runs.
Thus, the sequence of execution per the annotation for every test method is:
- @Before
- @Test
- @After
Remember that the tests though here, have been executed in sequential order i.e. test_JUnit1(), test_JUnit2(), test_JUnit3(), there is no sequence defined to the test, hence they may execute in order. Each test is isolated from the other test.
JUnit 4 Test – Example 2
Here, let’s quickly see how we can have a method that runs one time for the very first time in a class and another method that runs one time after all the tests are executed for the class.
Code:
package demo.tests; import static org.junit.Assert.*; import org.junit.After; import org.junit.Before; import org.junit.Test; public class JUnitProgram { @BeforeClass public static void preClass() { System.out.println("This is the preClass() method that runs one time before the class"); } @Before public void setUp() { System.out.println("_______________________________________________________\n"); System.out.println("This is the setUp() method that runs before each testcase"); } @Test public void test_JUnit1() { System.out.println("This is the testcase test_JUnit1() in this class"); } @Test public void test_JUnit2() { System.out.println("This is the testcase test_JUnit2() in this class"); } @Test public void test_JUnit3() { System.out.println("This is the testcase test_JUnit3() in this class"); } @After public void tearDown() { System.out.println("This is the tearDown() method that runs after each testcase"); System.out.println("_______________________________________________________\n"); } @AfterClass public static void postClass() { System.out.println("This is the postClass() method that runs one time after the class"); } }
We have added the preClass() method under @BeforeClass annotation. This method runs only one time for a class prior to the test execution. It runs even before the method under @Before executes.
The postClass() method under @AfterClass annotation runs once in the end when all the tests including the test under @After are executed and completed.
The sequence of the test run is as follows:
- @BeforeClass
- @Before
- @Test
- @After
- @AfterClass
The methods under @BeforeClass and @AfterClass are commonly shared by the class which is why if the methods are not declared as static then it gives an initialization error on execution of the test.
See the below screenshot, where we have not set the preClass() method under @BeforeClass annotation as static and thereby the test has errored on execution.
You may see the result showing an initialization Error which could be eliminated by marking the method as static. The same goes for the method postClass() under @AfterClass annotation.
Conclusion
We have tried to set a context on the good programming practices to be followed by implementing the Test Fixture approach and a basic understanding of usage and sequence of execution for the lifecycle annotations.
In our next tutorial, we learn about the different ways of executing JUnit tests in Eclipse. So keep tuned to the series as we progress with more interesting aspects of JUnit.
=> Check Here To See A-Z Of JUnit Training Tutorials Here.