JUnit 5 @BeforeEach and @AfterEach Example

By Arvind Rai, April 15, 2018
This page will walk through JUnit 5 @BeforeEach and @AfterEach example. @BeforeEach and @AfterEach annotations are the analogous to @Before and @After annotations respectively of JUnit 4. The methods annotated with @BeforeEach and @AfterEach execute before and after respectively for each method annotated with @Test, @RepeatedTest, @ParameterizedTest, or @TestFactory in current class. @BeforeEach and @AfterEach annotated methods must not be static and must not return a value otherwise they will throw runtime exception. We can use @BeforeEach and @AfterEach annotations with default methods of interface but cannot be used with static methods of interface. Now find the @BeforeEach and @AfterEach complete example step by step.

Technologies Used

Find the technologies being used in our example.
1. Java 9
2. JUnit 5
3. Gradle 4.3.1
4. Eclipse Oxygen.3a

Gradle Build File

Find the Gradle build file to resolve the JUnit 5 JAR dependencies.
build.gradle
apply plugin: 'java'
apply plugin: 'eclipse'
archivesBaseName = 'concretepage'
version = '1' 
repositories {
    mavenCentral()
}
dependencies {
    testCompile group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: '5.1.1'
    testCompile group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version: '5.1.1'
    testCompile group: 'org.junit.jupiter', name: 'junit-jupiter-params', version: '5.1.1'
    testCompile group: 'org.junit.platform', name: 'junit-platform-launcher', version: '1.1.1'
} 

@BeforeEach and @AfterEach with @Test

@Test annotation denotes that method is a test method. Here we will create methods annotated with @BeforeEach and @AfterEach and @Test. We will observe that the @BeforeEach annotated method will run before each @Test annotated method and @AfterEach annotated method will run after each @Test annotated method. Find the example.
UsingTestAnnotation.java
package com.concretepage;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInfo;

public class UsingTestAnnotation {
    @BeforeEach
    void init(TestInfo testInfo) {
    	System.out.println("Start..." + testInfo.getDisplayName());
    }
    @Test
    @DisplayName("Multiplication Test")
    void multiplyTest() {
    	System.out.println("---Inside multiplyTest---");
    	Utility utility = new Utility();
    	assertEquals(30, utility.multiplyNumbers(5, 6), "6 * 5 will be 30");
    }
    @Test
    @DisplayName("Add Test")
    void addTest() {
    	System.out.println("---Inside addTest---");
    	Utility utility = new Utility();
    	assertEquals(11, utility.addNumbers(5, 6), "6 + 5 will be 11");
    }    
    @AfterEach
    void tearDown(TestInfo testInfo) {
    	System.out.println("Finished..." + testInfo.getDisplayName());
    }
} 
We should take care that @BeforeEach and @AfterEach annotated methods must not be static and must not return a value otherwise they will throw runtime exception. @DisplayName is used to declare a custom display name for annotated test class or test method. TestInfo is used to get the information about the current test.
Output
Start...Add Test
---Inside addTest---
Finished...Add Test
Start...Multiplication Test
---Inside multiplyTest---
Finished...Multiplication Test 
Find the sample utility class that we are using in our example to write test cases.
Utility.java
package com.concretepage;
import java.util.Arrays;
import java.util.List;

public class Utility {
   List<String> allUsers = Arrays.asList("Mahesh", "Ram", "Krishn", "Arjun", "Bheem");	
   public long multiplyNumbers(int num1, int num2) {
	  return num1 * num2;
   }
   public long addNumbers(int num1, int num2) {
	  return num1 + num2;
   }   
   public boolean isUserAvailable(String userName) {
	  return allUsers.contains(userName); 
   }
} 

@BeforeEach and @AfterEach with @RepeatedTest

@RepeatedTest denotes that a method is a test template for a repeated test. Here we will create methods annotated with @BeforeEach and @AfterEach and @RepeatedTest. We will observe that @BeforeEach and @AfterEach annotated method will execute before and after respectively for every repeated execution of @RepeatedTest annotated method. Find the example.
UsingRepeatedTestAnnotation.java
package com.concretepage;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.RepeatedTest;
import org.junit.jupiter.api.TestInfo;

public class UsingRepeatedTestAnnotation {
    @BeforeEach
    void init(TestInfo testInfo) {
    	System.out.println("Start..." + testInfo.getDisplayName());
    }
    @RepeatedTest(3)
    void repeatedMultiplicationTest() {
    	System.out.println("---Inside repeatedMultiplicationTest---");
    	Utility utility = new Utility();
    	assertEquals(30, utility.multiplyNumbers(5, 6), "6 * 5 will be 30");
    }
    @AfterEach
    void tearDown(TestInfo testInfo) {
    	System.out.println("Finished..." + testInfo.getDisplayName());
    }	
} 
Output
Start...repetition 1 of 3
---Inside repeatedMultiplicationTest---
Finished...repetition 1 of 3
Start...repetition 2 of 3
---Inside repeatedMultiplicationTest---
Finished...repetition 2 of 3
Start...repetition 3 of 3
---Inside repeatedMultiplicationTest---
Finished...repetition 3 of 3 

@BeforeEach and @AfterEach with @ParameterizedTest

@ParameterizedTest denotes that method is parameterized test. Here we will create methods annotated with @BeforeEach and @AfterEach and @ParameterizedTest. The value for parameterized test is provided by @ValueSource annotation. The test method annotated with @ParameterizedTest will execute for each parameter provided by @ValueSource and for every execution of @ParameterizedTest method, the @BeforeEach and @AfterEach annotated method will also execute before and after respectively. Find the example.
UsingParameterizedTestAnnotation.java
package com.concretepage;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.TestInfo;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;

public class UsingParameterizedTestAnnotation {
    @BeforeEach
    void init(TestInfo testInfo) {
    	System.out.println("Start..." + testInfo.getDisplayName());
    }	
    @ParameterizedTest
    @ValueSource(strings = { "Krishn", "Arjun", "Bheem" })
    void checkUserAvailabilityTest(String userName) {
        System.out.println("---Inside checkUserAvailabilityTest---");
    	Utility utility = new Utility();
    	assertTrue(utility.isUserAvailable(userName), "User will exist");
    }
    @AfterEach
    void tearDown(TestInfo testInfo) {
    	System.out.println("Finished..." + testInfo.getDisplayName());
    }    
} 
Output
Start...[1] Krishn
---Inside checkUserAvailabilityTest---
Finished...[1] Krishn
Start...[2] Arjun
---Inside checkUserAvailabilityTest---
Finished...[2] Arjun
Start...[3] Bheem
---Inside checkUserAvailabilityTest---
Finished...[3] Bheem 

@BeforeEach and @AfterEach with @TestFactory

@TestFactory denotes that method is test factory for dynamic test. A dynamic test is a test case generated at run time. It is created using JUnit DynamicTest API. Here we will create methods annotated with @BeforeEach and @AfterEach and @TestFactory. A @TestFactory annotated method returns Stream, Collection, Iterable etc. In our example we are using @TestFactory with Stream. At run time the parameter for testing will be provided by Java Stream. In the dynamic test lifecycle @BeforeEach and @AfterEach methods are executed for the @TestFactory method but not for each dynamic test. The @BeforeEach annotated method will execute before execution of @TestFactory annotated method and @AfterEach annotated method will execute after complete execution of @TestFactory annotated method. Find the example.
UsingTestFactoryAnnotation.java
package com.concretepage;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.util.stream.Stream;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.DynamicTest;
import org.junit.jupiter.api.TestFactory;
import org.junit.jupiter.api.TestInfo;

public class UsingTestFactoryAnnotation {
    @BeforeEach
    void init(TestInfo testInfo) {
    	System.out.println("Start..." + testInfo.getDisplayName());
    }	
    @TestFactory
    @DisplayName("User Availability Test with @TestFactory")
    Stream<DynamicTest> userAvailabilityDynamicTest() {
    	System.out.println("---Inside userAvailabilityDynamicTest---");
    	Utility utility = new Utility();
        return Stream.of("Krishn", "Arjun", "Bheem")
            .map(userName -> DynamicTest.dynamicTest("Test " + userName, () -> { 
            	 System.out.println(userName);
            	 assertTrue(utility.isUserAvailable(userName), "User will exist");
             }));
    }  
    @AfterEach
    void tearDown(TestInfo testInfo) {
    	System.out.println("Finished..." + testInfo.getDisplayName());
    }    
} 
Output
Start...User Availability Test with @TestFactory
---Inside userAvailabilityDynamicTest---
Krishn
Arjun
Bheem
Finished...User Availability Test with @TestFactory 

@BeforeEach and @AfterEach with @Test, @RepeatedTest, @ParameterizedTest and @TestFactory

Here we will write test cases using @BeforeEach and @AfterEach with @Test, @RepeatedTest, @ParameterizedTest and @TestFactory altogether to check their order of execution. We will also use @BeforeAll and @AfterAll in test class. @BeforeAll annotated method executes only once before all test cases and @AfterAll annotated method executes only once after all test cases in current class. Find the example.
MyJUnitTests.java
package com.concretepage;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.util.stream.Stream;
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.DisplayName;
import org.junit.jupiter.api.DynamicTest;
import org.junit.jupiter.api.RepeatedTest;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestFactory;
import org.junit.jupiter.api.TestInfo;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;

public class MyJUnitTests {
    @BeforeAll
    static void initAll() {
    	System.out.println("---Inside initAll---");
    }
    @BeforeEach
    void init(TestInfo testInfo) {
    	System.out.println("Start..." + testInfo.getDisplayName());
    }	
    @Test
    @DisplayName("Multiplication Test")
    void multiplyTest() {
    	System.out.println("---Inside multiplyTest---");
    	Utility utility = new Utility();
    	assertEquals(30, utility.multiplyNumbers(5, 6), "6 * 5 will be 30");
    }
    @RepeatedTest(3)
    void repeatedMultiplicationTest() {
    	System.out.println("---Inside repeatedMultiplicationTest---");
    	Utility utility = new Utility();
    	assertEquals(30, utility.multiplyNumbers(5, 6), "6 * 5 will be 30");
    }
    @ParameterizedTest
    @ValueSource(strings = { "Krishn", "Arjun", "Bheem" })
    void checkUserAvailabilityTest(String userName) {
        System.out.println("---Inside checkUserAvailabilityTest---");
    	Utility utility = new Utility();
    	assertTrue(utility.isUserAvailable(userName), "User will exist");
    }	
    @TestFactory
    @DisplayName("User Availability Test with @TestFactory")
    Stream<DynamicTest> userAvailabilityDynamicTest() {
    	System.out.println("---Inside userAvailabilityDynamicTest---");
    	Utility utility = new Utility();
        return Stream.of("Krishn", "Arjun", "Bheem")
            .map(userName -> DynamicTest.dynamicTest("Test " + userName, () -> { 
            	 System.out.println(userName);
            	 assertTrue(utility.isUserAvailable(userName), "User will exist");
             }));
    }  
    @AfterEach
    void tearDown(TestInfo testInfo) {
    	System.out.println("Finished..." + testInfo.getDisplayName());
    } 
    @AfterAll
    static void tearDownAll() {
    	System.out.println("---Inside tearDownAll---");
    }
} 
Output
---Inside initAll---
Start...Multiplication Test
---Inside multiplyTest---
Finished...Multiplication Test
Start...[1] Krishn
---Inside checkUserAvailabilityTest---
Finished...[1] Krishn
Start...[2] Arjun
---Inside checkUserAvailabilityTest---
Finished...[2] Arjun
Start...[3] Bheem
---Inside checkUserAvailabilityTest---
Finished...[3] Bheem
Start...User Availability Test with @TestFactory
---Inside userAvailabilityDynamicTest---
Krishn
Arjun
Bheem
Finished...User Availability Test with @TestFactory
Start...repetition 1 of 3
---Inside repeatedMultiplicationTest---
Finished...repetition 1 of 3
Start...repetition 2 of 3
---Inside repeatedMultiplicationTest---
Finished...repetition 2 of 3
Start...repetition 3 of 3
---Inside repeatedMultiplicationTest---
Finished...repetition 3 of 3
---Inside tearDownAll--- 

@BeforeEach and @AfterEach with Interface Default Methods

We can use @BeforeEach and @AfterEach annotations with default methods of interface but cannot be used with static methods of interface. Here we will create a lifecycle logger interface and then create @BeforeEach and @AfterEach annotated methods as default methods. To use our lifecycle logger interface we will create a test class by implementing our logger interface.
LifecycleLogger.java
package com.concretepage;
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.TestInfo;

public interface LifecycleLogger {
    @BeforeAll
    static void initAll() {
    	System.out.println("---Inside initAll---");
    }
    @BeforeEach
    default void init(TestInfo testInfo) {
    	System.out.println("Start..." + testInfo.getDisplayName());
    }	
    @AfterEach
    default void tearDown(TestInfo testInfo) {
    	System.out.println("Finished..." + testInfo.getDisplayName());
    } 
    @AfterAll
    static void tearDownAll() {
    	System.out.println("---Inside tearDownAll---");
    }    
} 
MyMultiplicationTest.java
package com.concretepage;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

public class MyMultiplicationTest implements LifecycleLogger {
    @Test
    @DisplayName("Multiplication Test")
    void multiplyTest() {
    	System.out.println("---Inside multiplyTest---");
    	Utility utility = new Utility();
    	assertEquals(30, utility.multiplyNumbers(5, 6), "6 * 5 will be 30");
    }
} 
Output
---Inside initAll---
Start...Multiplication Test
---Inside multiplyTest---
Finished...Multiplication Test
---Inside tearDownAll--- 
To run the example, download the source code and import into Eclipse Oxygen IDE. To run a test class, right click on the test class -> Run As -> JUnit Test. We will get output in console. If we are using JUnit 4 environment to run JUnit 5 examples then we need to annotate our test class with @RunWith(JUnitPlatform.class) annotation. Eclipse Oxygen.1a onwards provides JUnit 5 environment. In our example, we are using Eclipse Oxygen.3a to run test classes.

Reference

JUnit 5 User Guide

Download Source Code

POSTED BY
ARVIND RAI
ARVIND RAI
LEARN MORE








©2024 concretepage.com | Privacy Policy | Contact Us