junit5

Junit5 tutorial: Part2

Before exploring this part, please read first part 1 is here.

Junit5 for beginners. In this tutorial let us make our hands dirty and have practical experience. If you are using Maven or Gradle for either of the build tool you can use dependency.

Maven dependency for Junit 5.0:

Add below dependency in pom.xml.

<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.1.0</version>
<scope>test</scope>
</dependency>

Junit 5.0 with Gradle:

Add below dependency in build.gradle file. We can start by supplying the unit test platform to the build tool. Now we have specified test platform as Junit.

test {useJUnitPlatform()}

Now after the above steps, we need to provide Junit5 dependencies here is the difference between Junit4 and junit5. As we have discussed in previous article Junit5 is modular so we have three different modules and each one has a different purpose.

dependencies 
{
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.3.1'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.3.1'
}

In JUnit 5, though, the API is separated from the runtime, meaning two dependencies have to provide testImplementation and timeRuntimeOnly respectively.

The API is manifest with junit-jupiter-api. The runtime is junit-jupiter-engine for JUnit 5, and junit-vintage-engine for JUnit 3 or 4.

1. JUnit Jupiter:

In the first article, we have explored the difference between Junit4 and Juni5. There are new annotations introduced as part of this module. JUnit 5 new annotations in comparison to JUnit 4 are:

@Tag — Mark tags to test method or test classes for filtering tests.

@ExtendWith —Register custom extensions.

@Nested — Used to create nested test classes.

@TestFactory — Mark or denotes a method is a test factory for dynamic tests.

@BeforeEach — The method annotated with this annotation will be run before each test method in the test class. (Similar to Junit4 @Before )

@AfterEach — The method annotated with this annotation will be executed after each test method. (Similar to Junit4 @After )

@BeforeAll — The method annotated with this annotation will be executed before all test methods in the current class. (Similar to Junit4 @BeforeClass )

@AfterAll — The method annotated with this annotation will be executed after all test methods in the current class. (Similar to Junit4 @AfterClass )

@Disable — This is used to disable a test class or method (Similar to Junit4 @Ignore)

@DisplayName — This annotation defines a custom display name for a test class or a test method.

2. JUnit Vintage:

As part of this module, there is no new annotation has introduced but the purpose of this module is to supports running JUnit 3 and JUnit 4 based tests on the JUnit 5 platform.

Let us deep dive and do some coding:

@DisplayName and @Disabled:

As you can capture from the below code snipept you can DisplayName I have just given two flavors of one method. This way you can provide your own custom display name to identify test easily.

@DisplayName("Happy Scenario")
@Test
void testSingleSuccessTest() 
{
System.out.println("Happy Scenario");
}

@Test
@DisplayName("Failure scenario")
void testFailScenario() {
System.out.println("Failure scenario")
}

To disable test cases which implementation not yet completed or some other reason to skip that

@Test
@Disabled("Under constructution")
void testSomething() {
}

@BeforeAll and @BeforeEach :

BeforeAll is like a setup method this will get invoked once before all test methods in this test class and BeforeEach get invoked before each test method in this class.

@BeforeAll annotation must be, static and it’s run once before any test method is run.

@BeforeAll
static void setup() {
System.out.println("@BeforeAll: get executes once before all test methods in this class");
System.out.println("This is like setup for tests methods");
}

@BeforeEach
void init() {
System.out.println("@BeforeEach: get executes before each test method in this class");
System.out.println("initialisation before each test method");
}

@AfterEach and @AfterAll:

AfterEach gets invoked after each test method in this class and AfterAll get invoked after all test cases get invoked. Afterall like finalization task.

@AfterAll annotation must be, static and it’s run once after all test methods have been run.

@AfterEach
void tearDown() {
System.out.println("@AfterEach: get executed after each test method.");
}
@AfterAllstatic void finish() {
System.out.println("@AfterAll: get executed after all test methods.");
}

Assertions and Assumptions:

Assertions and assumptions are the base of unit testing. Junit5 taking full advantage of Java8 features such as lambda to make assertions simple and effective.

Assertions:

Junit5 assertions are part of a org.junit.jupiter.api.Assertions API and improvision have significantly as Java 8 is the base of Junit5 you can leverage all the features of Java8 primarily lambada expression. Assertions help in validating the expected output with the actual output of a test case.

@Test
void testLambdaExpression() {
assertTrue(Stream.of(4, 5, 9)
.stream()
.mapToInt(i -> i)
.sum() > 18, () -> "Sum should be greater than 18");
}

As you are aware of using lambda expression because of lambda expression

All JUnit Jupiter assertions are static methods

@Test
void testCase()
{
//Pass
Assertions.assertNotEquals(3, Calculator.add(2, 2));

//Fail
Assertions.assertNotEquals(4, Calculator.add(2, 2), "Calculator.add(2, 2) test failed");

//Fail
Supplier<String> messageSupplier = ()-> "Calculator.add(2, 2) test failed";
Assertions.assertNotEquals(4, Calculator.add(2, 2), messageSupplier);
}

With assertAll()which will report any failed assertions within the group with a MultipleFailuresError