In this post under JUnit, I will show with example the purpose of BeforeEach and AfterEach annotations.
As you know when writing unit test cases, before calling the test method and asserting the output, we should first setup the data on which the test method has to be executed. We can place the code that’s sets up data at one of these two places
1) If the setup data differs for each test method, then place the setup code in each method. As shown in the below code
class CalculatorTest {
private Calculator calculator = new Calculator();
@Test
void testAdd() {
calculator.setX(5);
calculator.setY(10);
assertEquals(15, calculator.add());
}
@Test
void testSubstract() {
calculator.setX(10);
calculator.setY(5);
assertEquals(5, calculator.sub());
}
}
In the above code, we are testing Calculator class “add” and “substract” method. The setup data is different for each method. For “add” method we set X as 5, Y as 10 and for “substract” method we set X as 10 and Y as 5.
So we place the code that sets up data in their corresponding test methods “testAdd” and “testSubstract”.
2) If the setup data doesn’t differs for each test method, then we can place the setup code in a common method, that will be called by each test method before calling the test method and asserting the output. As shown in the below code.
public class PredicateExample1 {
private List<Apple> inputList;
private void setup() {
inputList = new ArrayList<>(0);
inputList.add(new Apple("Yellow", 1));
inputList.add(new Apple("Green", 2));
inputList.add(new Apple("Green", 5));
inputList.add(new Apple("Red", 5));
}
private void tearDown() {
inputList.clear();
inputList = null;
}
@Test
public void testFilterBySize() {
setup();
PredicateExample predicateExample = new PredicateExample();
List<Apple> outputList = predicateExample.filterBySize(inputList, 5);
assertFalse(outputList.isEmpty());
assertEquals(2, outputList.size());
tearDown();
}
@Test
public void testFilterByColor() {
setup();
PredicateExample predicateExample = new PredicateExample();
List<Apple> outputList = predicateExample.filtedByColor(inputList, "Green");
assertFalse(outputList.isEmpty());
assertEquals(2, outputList.size());
tearDown();
}
}
In the above code, we test the “PredicateExample” class “filterBySize” method and “filtedByColor” method. The setup data is same for both the test methods. In every test method before calling the test method and asserting the output, we call the “setup” method to setup the data and at the end of test method we call “tearDown” method to clear the data.
The problem with this approach is that developer has to call “setup” and “tearDown” methods in each test method without miss. If missed the test method will behave differently and some times it throws compiler error.
To avoid this human error, JUnit provides “BeforeEach” and “AfterEach” annotations. Any method marked with “BeforeEach” is called before execution of every test method. Any method marked with “AfterEach” is called after execution of every test method.
As a result before every test method is executed, the data is setup and at the end of every test method the data is cleared. So each method will have freshly populated data to work on when executing another test case.
Below is the code showing how to use these annotations.
Test Class
package Package4;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import java.util.ArrayList;
import java.util.List;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
public class PredicateTest {
private List<Apple> inputList;
@BeforeEach
public void setup() {
inputList = new ArrayList<>(0);
inputList.add(new Apple("Yellow", 1));
inputList.add(new Apple("Green", 2));
inputList.add(new Apple("Green", 5));
inputList.add(new Apple("Red", 5));
}
@Test
public void testFilterBySize() {
PredicateExample predicateExample = new PredicateExample();
List<Apple> outputList = predicateExample.filterBySize(inputList, 5);
assertFalse(outputList.isEmpty());
assertEquals(2, outputList.size());
}
@Test
public void testFilterByColor() {
PredicateExample predicateExample = new PredicateExample();
List<Apple> outputList = predicateExample.filtedByColor(inputList, "Green");
assertFalse(outputList.isEmpty());
assertEquals(2, outputList.size());
}
@AfterEach
public void tearDown() {
inputList.clear();
inputList = null;
}
}
As you can see in the above, the “setup” method is marked with “BeforeEach” annotation and “tearDown” method is marked with “AfterEach” annotation.
Below is the class to be tested.
Class to be tested
package Package4;
import java.util.ArrayList;
import java.util.List;
public class PredicateExample {
public List<Apple> filterBySize(List<Apple> apples, int size) {
List<Apple> filteredApples = new ArrayList<>(0);
apples.forEach((apple) -> {if(apple.getSize() == size) filteredApples.add(apple);});
return filteredApples;
}
public List<Apple> filtedByColor(List<Apple> apples, String color) {
List<Apple> filteredApples = new ArrayList<>(0);
apples.forEach((apple -> {if(apple.getColor().equals(color)) filteredApples.add(apple);}));
return filteredApples;
}
}
class Apple {
private String color;
private int size;
public Apple(String color, int size) {
this.color = color;
this.size = size;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
}