JUnit 5 @BeforeEach and @AfterEach Example
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.
Contents
- Technologies Used
- Gradle Build File
- @BeforeEach and @AfterEach with @Test
- @BeforeEach and @AfterEach with @RepeatedTest
- @BeforeEach and @AfterEach with @ParameterizedTest
- @BeforeEach and @AfterEach with @TestFactory
- @BeforeEach and @AfterEach with @Test, @RepeatedTest, @ParameterizedTest and @TestFactory
- @BeforeEach and @AfterEach with Interface Default Methods
- Reference
- Download Source Code
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()); } }
@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
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()); } }
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()); } }
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()); } }
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---"); } }
---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---"); } }
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"); } }
---Inside initAll--- Start...Multiplication Test ---Inside multiplyTest--- Finished...Multiplication Test ---Inside tearDownAll---
@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.