Junit 5 Tutorial for Beginners
Tags: java, junit5, beginners, programming
Published: 2021-01-03 11:27:57

---
title: Junit 5 Tutorial for Beginners
published: true
description: 
tags: java, junit5, beginners, programming
cover_image: https://i1.wp.com/programmingtechie.com/wp-content/uploads/2020/12/Junit-5-Featured-Image-1.png?w=1280&ssl=1
---

**This post was originally published in [programmingtechie.com](https://programmingtechie.com/)**

Junit 5 is one of the popular testing frameworks in the Java Development World and it supports the latest features of Java 8.

If you are a visual learner like me, check out the below video tutorial:
{% youtube bx-ZtLbGDHw %}

##Table of Contents
  * [Junit 5 Architecture](#chapter-1)
     * [Junit Platform](#chapter-2)
     * [Junit Jupiter](#chapter-3)
     * [Junit Vintage](#chapter-4)
  * [Source Code for Project under Test](#chapter-5)
     * [Source Code for Starter Project](#chapter-6)
  * [Writing our First Test](#chapter-7)
  * [Testing Exceptions using assertThrows()](#chapter-8)
  * [Understanding Test Lifecycle](#chapter-9)
     * [Implementing Lifecycle Annotations in our Test](#chapter-10)
     * [@BeforeAll and @AfterAll](#chapter-11)
     * [@BeforeEach and @AfterEach](#chapter-12)
     * [Default Test Instance Lifecycle](#chapter-13)
     * [Changing Default Test Instance Lifecycle](#chapter-14)
  * [Conditional Executions](#chapter-15)
  * [Assumptions](#chapter-16)
  * [Repeated Tests](#chapter-17)
  * [Parameterized Tests](#chapter-18)
     * [ValueSource](#chapter-19)
     * [MethodSource](#chapter-20)
     * [CsvSource](#chapter-21)
     * [CsvFileSource](#chapter-22)
  * [Disabled Tests](#chapter-23)
  * [Nested Tests](#chapter-24)
  * [Running Tests using Maven Surefire Plugin](#chapter-25)
  * [Conclusion](#chapter-26)

Even though JUnit 5 is a successor for Junit 4, the architecture of the framework is completely different, so let’s have a look at the Architecture of Junit 5.

##Junit 5 Architecture<a name="chapter-1"></a>
The Architecture of Junit 5 can be divided into 3 different projects:

* Junit Platform
* Junit Jupiter
* Junit Vintage

## Junit Platform<a name="chapter-2"></a>
The Junit Platform project provides an API to launch the tests from either the IDE’s, Build Tools or Console. It defines a `TestEngine` API which enables development of new Testing Frameworks on top of the Platform.

## Junit Jupiter<a name="chapter-3"></a>
This project provides API to write our Junit tests and extensions, it contains new annotations and a `TestEngine` implementation to run these tests on the platform.

## Junit Vintage<a name="chapter-4"></a>
This project provides a `TestEngine` implementation to support backward compatibility for tests written with Junit 3 and Junit4.

You can check the architecture Diagram below:

![Junit 5 Architecture Diagram](https://programmingtechie.com/wp-content/uploads/2021/01/junit-5.png)

#Source Code for Project under Test<a name="chapter-5"></a>
We are going to use a Contact Manager Application while learning how to write tests using Junit 5.

You can download the source code of the application from the below Github Link:
https://github.com/SaiUpadhyayula/contact-manager

##Source Code for Starter Project<a name="chapter-6"></a>
If you want to follow along this tutorial, have a look at the Starter Repository which is in the same state as the start of the tutorial.

https://github.com/SaiUpadhyayula/contact-manager-starter

The Application uses Maven to manage the dependencies and build the project. If you want to learn Maven, you can check out my [Complete Maven Tutorial](https://programmingtechie.com/2020/12/05/complete-maven-tutorial/) blog post. The application mainly contains 2 classes, `Contact.java` and `ContactManager.java`

**Contact.java**
```
public class Contact {
    private String firstName;
    private String lastName;
    private String phoneNumber;

    public Contact(String firstName, String lastName, String phoneNumber) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.phoneNumber = phoneNumber;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getPhoneNumber() {
        return phoneNumber;
    }

    public void setPhoneNumber(String phoneNumber) {
        this.phoneNumber = phoneNumber;
    }

    public void validateFirstName() {
        if (this.firstName == null)
            throw new RuntimeException("First Name Cannot be null");
    }

    public void validateLastName() {
        if (this.lastName == null)
            throw new RuntimeException("Last Name Cannot be null");
    }

    public void validatePhoneNumber() {
        if (this.phoneNumber.length() != 10) {
            throw new RuntimeException("Phone Number Should be 10 Digits Long");
        }
        if (!this.phoneNumber.matches("\\d+")) {
            throw new RuntimeException("Phone Number Contain only digits");
        }
        if (!this.phoneNumber.startsWith("0")) {
            throw new RuntimeException("Phone Number Should Start with 0");
        }
    }
}
```
This class just contains 3 necessary fields: First Name, Last Name and Phone Number.

**ContactManager.java**
```
import java.util.Collection;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class ContactManager {

    Map<String, Contact> contactList = new ConcurrentHashMap<String, Contact>();

    public void addContact(String firstName, String lastName, String phoneNumber) {
        Contact contact = new Contact(firstName, lastName, phoneNumber);
        validateContact(contact);
        checkIfContactAlreadyExist(contact);
        contactList.put(generateKey(contact), contact);
    }

    public Collection<Contact> getAllContacts() {
        return contactList.values();
    }

    private void checkIfContactAlreadyExist(Contact contact) {
        if (contactList.containsKey(generateKey(contact)))
            throw new RuntimeException("Contact Already Exists");
    }

    private void validateContact(Contact contact) {
        contact.validateFirstName();
        contact.validateLastName();
        contact.validatePhoneNumber();
    }

    private String generateKey(Contact contact) {
        return String.format("%s-%s", contact.getFirstName(), contact.getLastName());
    }
}
```
This class contains the main business logic to maintain contact information.

#Writing our First Test<a name="chapter-7"></a>

Now it is time to write our first Junit 5 Test.

I am going to create a test class called as `ContactManagerTest.java` under the `src/test/java` folder.

**ContactManagerTest.java**
```
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.*;

public class ContactManagerTest {

    @Test
    @DisplayName("Should Create Contact")
    public void shouldCreateContact() {
        ContactManager contactManager = new ContactManager();
        contactManager.addContact("John", "Doe", "0123456789");
        assertFalse(contactManager.getAllContacts().isEmpty());
        assertEquals(1, contactManager.getAllContacts().size());
    }
}
```
* We created a method called `shouldCreateContact()` which is the method testing, the contact creation.
Junit understands that this method is a Test, by looking at the `@Test` annotation.
* By looking at the method name `shouldCreateContact()` we understand what the method is trying to do, but we can also provide a custom name for this method using the `@DisplayName` annotation.
* Inside the method, we created a contact by providing the first name, last name and phone number details to the `addContact()` method of the `ContactManager` class.
* We can retrieve all the contact information through the `getAllContacts()` method.
* As a last step, we are verifying that the result of `getAllContacts()` is not empty, and the size of the `getAllContacts()` List is exactly 1.

The process of verifying the actual output with the expected output is called as performing assertions.

Junit 5 provides many different methods to perform assertions for different cases.

We have Assertions class which provides number of static methods, we can use in our tests.

If you run the above test in IntelliJ, the test will be green. Congratulations, you wrote your first Junit 5 test.

![Junit 5 Intellij Test Result](https://programmingtechie.com/wp-content/uploads/2020/12/image.png)

You can find more details about this class in the documentation - https://junit.org/junit5/docs/5.0.1/api/org/junit/jupiter/api/Assertions.html

# Testing Exceptions using assertThrows()<a name="chapter-8"></a>

In our first test case, we successfully tested the Happy Path.

Now let's explore some other scenarios.

Here are some validations which are performed when creating a Contact:

* First Name should not be null
* Last Name should not be null
* Phone Number Should :
* Be Exactly 10 Digits Long
* Contain only Digits
* Start with 0

Let's write test cases to test some of the above cases, we will cover all the scenarios in the upcoming sections.

**ContactManagerTest.java**

```
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;

public class ContactManagerTest {

    @Test
    @DisplayName("Should Create Contact")
    public void shouldCreateContact() {
        ContactManager contactManager = new ContactManager();
        contactManager.addContact("John", "Doe", "0123456789");
        assertFalse(contactManager.getAllContacts().isEmpty());
        assertEquals(1, contactManager.getAllContacts().size());
    }

    @Test
    @DisplayName("Should Not Create Contact When First Name is Null")
    public void shouldThrowRuntimeExceptionWhenFirstNameIsNull() {
        ContactManager contactManager = new ContactManager();
        Assertions.assertThrows(RuntimeException.class, () -> {
            contactManager.addContact(null, "Doe", "0123456789");
        });
    }
}

```
* The 2nd Test Case, tests whether the Contact Creation is Failed when we enter the First Name as Null.
* We are asserting that the `addContact()` method throws a `RuntimeException`
* We can assert the Exceptions using the `assertThrow()` method from the Assertions class
* The `assertThrow()` method takes the Exception Type as the first parameter and the Executable which is throws the Exception as the second parameter.

We can write similar test cases also for the fields Last Name and Phone Number like below:

**ContactManagerTest.java**
```
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;

public class ContactManagerTest {

    @Test
    @DisplayName("Should Create Contact")
    public void shouldCreateContact() {
        ContactManager contactManager = new ContactManager();
        contactManager.addContact("John", "Doe", "0123456789");
        assertFalse(contactManager.getAllContacts().isEmpty());
        assertEquals(1, contactManager.getAllContacts().size());
    }

    @Test
    @DisplayName("Should Not Create Contact When First Name is Null")
    public void shouldThrowRuntimeExceptionWhenFirstNameIsNull() {
        ContactManager contactManager = new ContactManager();
        Assertions.assertThrows(RuntimeException.class, () -> {
            contactManager.addContact(null, "Doe", "0123456789");
        });
    }

    @Test
    @DisplayName("Should Not Create Contact When Last Name is Null")
    public void shouldThrowRuntimeExceptionWhenLastNameIsNull() {
        ContactManager contactManager = new ContactManager();
        Assertions.assertThrows(RuntimeException.class, () -> {
            contactManager.addContact("John", null, "0123456789");
        });
    }

    @Test
    @DisplayName("Should Not Create Contact When Phone Number is Null")
    public void shouldThrowRuntimeExceptionWhenPhoneNumberIsNull() {
        ContactManager contactManager = new ContactManager();
        Assertions.assertThrows(RuntimeException.class, () -> {
            contactManager.addContact("John", "Doe", null);
        });
    }
}

```
You can observe that I added similar test cases for the Phone Number and Last Name fields as well.

You should see the below output when running the tests:
![Junit5 Test Results IntelliJ](https://programmingtechie.com/wp-content/uploads/2020/12/image-1.png)

#Understanding Test Lifecycle<a name="chapter-8"></a>

Now let's go ahead and understand the Lifecycle of Junit Tests. Each Test undergoes different phases as part of it's execution, each phase is represented by an Annotation.

* **@BeforeAll**

The method marked with this annotation will be executed before any of the `@Test` methods are executed inside the Test class.
* **@BeforeEach**

The method marked with this annotation will be executed before each `@Test` method in the Test class.
* **@AfterEach**

The method marked with this annotation will be executed after each `@Test` method in the Test class.
* **@AfterAll**

The method marked with this annotation will be executed after all the `@Test` methods are executed in the Test class.

The Before methods (**@BeforeAll**, **@BeforeEach**) perform some initialization actions like setting up of test data or environment data, before executing the tests.

The After methods (**@AfterAl**l, **@AfterEach**) perform clean up actions like cleaning up of created Environment Data or Test Data.

**@BeforeAll** and **@AfterAll** are called only once for the entire test, and the methods are usually marked as **static**.

![Junit 5 Test Lifecycle](https://programmingtechie.com/wp-content/uploads/2020/12/junit5_test_lifecycle.png)

##Implementing Lifecycle Annotations in our Test<a name="chapter-10"></a>

So now, let’s see how we can use the above mentioned Lifecycle annotations, in our test.

In our 4 tests, we can observe that we are creating an instance of **ContactManager** at the start of each test.

This logic can go inside the method which is marked with either **@BeforeAll** or **@BeforeEach**

## @BeforeAll and @AfterAll<a name="chapter-11"></a>

```
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
 
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
 
public class ContactManagerTest {
 
    private static ContactManager contactManager;
 
    @BeforeAll
    public static void setup() {
        System.out.println("Instantiating Contact Manager before the Test Execution");
        contactManager = new ContactManager();
    }
 
    @Test
    @DisplayName("Should Create Contact")
    public void shouldCreateContact() {
        contactManager.addContact("John", "Doe", "0123456789");
        assertFalse(contactManager.getAllContacts().isEmpty());
        assertEquals(1, contactManager.getAllContacts().size());
    }
 
    @Test
    @DisplayName("Should Not Create Contact When First Name is Null")
    public void shouldThrowRuntimeExceptionWhenFirstNameIsNull() {
        ContactManager contactManager = new ContactManager();
        Assertions.assertThrows(RuntimeException.class, () -> {
            contactManager.addContact(null, "Doe", "0123456789");
        });
    }
 
    @Test
    @DisplayName("Should Not Create Contact When Last Name is Null")
    public void shouldThrowRuntimeExceptionWhenLastNameIsNull() {
        ContactManager contactManager = new ContactManager();
        Assertions.assertThrows(RuntimeException.class, () -> {
            contactManager.addContact("John", null, "0123456789");
        });
    }
 
    @Test
    @DisplayName("Should Not Create Contact When Phone Number is Null")
    public void shouldThrowRuntimeExceptionWhenPhoneNumberIsNull() {
        ContactManager contactManager = new ContactManager();
        Assertions.assertThrows(RuntimeException.class, () -> {
            contactManager.addContact("John", "Doe", null);
        });
    }
}
```
I created a method called as `setup()` which is marked with `@BeforeAll` annotation, inside this method, I instantiated the **ContactManager** and assigned the object to the `static` variable.

I also added a method called as `tearDown()` which is marked with `@AfterAll` annotation, we expect this method to be executed at the end of the test.

If you run the tests again, you should see the output like you see in the below image:

![Test Execution With BeforeAll and AfterAll](https://i2.wp.com/programmingtechie.com/wp-content/uploads/2020/12/image-2.png?resize=1536%2C450&ssl=1)

##@BeforeEach and @AfterEach<a name="chapter-12"></a>

By using this annotation, we can perform some operations which needs to be done Before and After Each Test Execution.

Note that, Junit always creates a new instance of the test before executing each `@Test` method.

```
import org.junit.jupiter.api.*;
 
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
 
public class ContactManagerTest {
 
    private ContactManager contactManager;
 
    @BeforeAll
    public static void setupAll() {
        System.out.println("Should Print Before All Tests");
    }
 
    @BeforeEach
    public void setup() {
        System.out.println("Instantiating Contact Manager");
        contactManager = new ContactManager();
    }
 
    @Test
    @DisplayName("Should Create Contact")
    public void shouldCreateContact() {
        contactManager.addContact("John", "Doe", "0123456789");
        assertFalse(contactManager.getAllContacts().isEmpty());
        assertEquals(1, contactManager.getAllContacts().size());
    }
 
    @Test
    @DisplayName("Should Not Create Contact When First Name is Null")
    public void shouldThrowRuntimeExceptionWhenFirstNameIsNull() {
        Assertions.assertThrows(RuntimeException.class, () -> {
            contactManager.addContact(null, "Doe", "0123456789");
        });
    }
 
    @Test
    @DisplayName("Should Not Create Contact When Last Name is Null")
    public void shouldThrowRuntimeExceptionWhenLastNameIsNull() {
        Assertions.assertThrows(RuntimeException.class, () -> {
            contactManager.addContact("John", null, "0123456789");
        });
    }
 
    @Test
    @DisplayName("Should Not Create Contact When Phone Number is Null")
    public void shouldThrowRuntimeExceptionWhenPhoneNumberIsNull() {
        Assertions.assertThrows(RuntimeException.class, () -> {
            contactManager.addContact("John", "Doe", null);
        });
    }
 
    @AfterEach
    public void tearDown() {
        System.out.println("Should Execute After Each Test");
    }
 
    @AfterAll
    public static void tearDownAll() {
        System.out.println("Should be executed at the end of the Test");
    }
}
```
I moved the logic to create the `ContactManager` object inside the `setup()` method marked with `@BeforeEach` and I renamed the method marked with `@BeforeAll` to `setupAll()`

I also introduced a new method called as `tearDown()` which is just logging some random text, just to show you that the method is executing after each test execution.

If you run the above test, this is how the output should look like:

![Test Execution Junit 5 BeforeEach and AfterEach](https://i0.wp.com/programmingtechie.com/wp-content/uploads/2020/12/image-3.png?resize=1536%2C658&ssl=1)

##Default Test Instance Lifecycle<a name="chapter-13"></a>

As mentioned above, Junit instantiates the Test class for each method marked with `@Test`.

For this reason, the method marked with `@BeforeAll` and `@AfterAll` should be marked with `static`.

##Changing Default Test Instance Lifecycle<a name="chapter-14"></a>

You can change this default behavior, by instructing Junit to create an instance of the Test class, only once using the below annotation.

`@TestInstance(Lifecylce.PER_CLASS)`

By using the above annotation, there is no need to mark the `@BeforeAll` and `@AfterAll` methods as `static`.

#Conditional Executions<a name="chapter-15"></a>

We can execute the `@Test` methods in our class based on a specific condition, for example: imagine if you developed a specific functionality on Linux for our Contact Manager application. After saving the contact, we are performing some additional logic which is specific to Linux Operating System.

Then we have to make sure that the test should only run when it’s running only on Linux Operating System.

You can enable this conditional execution using different annotations:
* @EnabledOnOs
* @DisabledOnOs

These annotations take the values for usual Operating Systems like **MAC**, **LINUX**, **WINDOWS**.

You can see the example usage of this annotation below:

```
@Test
@DisplayName("Should Create Contact")
@EnabledOnOs(value = OS.MAC, disabledReason = "Should Run only on MAC")
public void shouldCreateContact() {
    contactManager.addContact("John", "Doe", "0123456789");
    assertFalse(contactManager.getAllContacts().isEmpty());
    assertEquals(1, contactManager.getAllContacts().size());
}
```
We can also provide a reason using the disabledReason field, you can see the output in the below image:

![Junit 5 Disabled Tests](https://i0.wp.com/programmingtechie.com/wp-content/uploads/2020/12/image-4.png?resize=1536%2C731&ssl=1)

#Assumptions<a name="chapter-16"></a>

We can also perform conditional Assertions using Junit 5 **Assumptions**.

There may be particular test cases you want to make sure that you are running based on certain conditions.

You can have some test cases which should be executed only on Developer Machine but not on CI environment.

Or you can also have some slow running tests, you can enable on disable them based on certain conditions.

You can perform this assumptions in Junit 5 similar to the Assertions.

```
@Test
@DisplayName("Test Contact Creation on Developer Machine")
public void shouldTestContactCreationOnDEV() {
    Assumptions.assumeTrue("DEV".equals(System.getProperty("ENV")));
    contactManager.addContact("John", "Doe", "0123456789");
    assertFalse(contactManager.getAllContacts().isEmpty());
    assertEquals(1, contactManager.getAllContacts().size());
}
```
* In the above test, you can see that we are using the Assumptions.assumeTrue() method to execute the tests, only when the ENV System Property is equal to DEV.
* If the above assumption failed, then the test will not be executed.

Here is the output when the assumptions is failed:

![Assumptions](https://i1.wp.com/programmingtechie.com/wp-content/uploads/2020/12/image-5.png?resize=1536%2C397&ssl=1)

Now let’s go ahead and add the System Property **ENV** to the VM Options of the `ContactManagerTest` class, you can do that by clicking on the **Edit Configuration** options for the Test inside IntelliJ.

![Edit Configuration for Test](https://i0.wp.com/programmingtechie.com/wp-content/uploads/2020/12/image-6.png?w=1008&ssl=1)

Once you run the test after activating this property, you can see that the test is executed successfully.

![Test Result for Assumptions](https://i2.wp.com/programmingtechie.com/wp-content/uploads/2020/12/image-7.png?w=1153&ssl=1)

#Repeated Tests<a name="chapter-17"></a>

If you have any functionality which has some randomness to it, you may want to create and run that test multiple times, to make sure that the functionality is working as expected.

Junit 5 provides us the `@RepeatedTest` annotation to fulfil this requirement.

You can repeat the Test N number of time by passing the number as an argument to the annotation.Eg: `@RepeatedTest(5)` will run the test marked with this annotation 5 times.

```
@DisplayName("Repeat Contact Creation Test 5 Times")
@RepeatedTest(5)
public void shouldTestContactCreationRepeatedly() {
    contactManager.addContact("John", "Doe", "0123456789");
    assertFalse(contactManager.getAllContacts().isEmpty());
    assertEquals(1, contactManager.getAllContacts().size());
}
```
If you run the above test, you can see the below output:

![Repeated Tests](https://i0.wp.com/programmingtechie.com/wp-content/uploads/2020/12/image-8.png?w=1170&ssl=1)

You can create that IntelliJ displays an expandable node where you can see the output for each repetition.

You can also specify custom names instead of the default repetition 1 of 5, using the name field.

Eg:
`@RepeatedTest(value = 5,
        name = "Repeating Contact Creation Test {currentRepetition} of {totalRepetitions}")`

```
@DisplayName("Repeat Contact Creation Test 5 Times")
@RepeatedTest(value = 5,
        name = "Repeating Contact Creation Test {currentRepetition} of {totalRepetitions}")
public void shouldTestContactCreationRepeatedly() {
    contactManager.addContact("John", "Doe", "0123456789");
    assertFalse(contactManager.getAllContacts().isEmpty());
    assertEquals(1, contactManager.getAllContacts().size());
}
```
When you run the above test, you can see the below output:

![Junit 5 Repeating Tests](https://i2.wp.com/programmingtechie.com/wp-content/uploads/2020/12/image-9.png?w=790&ssl=1)

#Parameterized Tests<a name="chapter-18"></a>

You can also run parametrized tests by running a test multiple times and providing different set of inputs for each repetition.

We have to add the `@ParameterizedTest` annotation to mark a test method as Parameterized Test.

```
@Test
@DisplayName("Phone Number should start with 0")
public void shouldTestPhoneNumberFormat() {
    contactManager.addContact("John", "Doe", "0123456789");
    assertFalse(contactManager.getAllContacts().isEmpty());
    assertEquals(1, contactManager.getAllContacts().size());
}
```
In the above testcase, we are checking whether the provided phone number is in the required format or not. i.e.. If the Phone Number is starting with 0

We can run this test against different set’s of input and make sure that the test is working as expected or not.

You can provide the input to the test using different ways:

##ValueSource<a name="chapter-19"></a>

You can provide input to the Parameterized Test using the `@ValueSource` annotation where you can provide a set of `string`, `long`, `double`, `float` literals to our test.

Eg: `@ValueSource(strings = {“string1″,”string2″,”string3”})`

Then you can access this string inside the test by first adding a String parameter to our test.

```
@DisplayName("Phone Number should match the required Format")
@ParameterizedTest
@ValueSource(strings = {"0123456789", "1234567890", "+0123456789"})
public void shouldTestPhoneNumberFormat(String phoneNumber) {
    contactManager.addContact("John", "Doe", phoneNumber);
    assertFalse(contactManager.getAllContacts().isEmpty());
    assertEquals(1, contactManager.getAllContacts().size());
}
```
In the above example we are providing the Phone Number String in different formats.

If you run the above test, it provides the below output

![Value Source](https://i2.wp.com/programmingtechie.com/wp-content/uploads/2020/12/image-9.png?w=790&ssl=1)

The Test verifies whether the Phone Number starts with 0 or not, as we provided invalid inputs for the 2nd and 3rd cases, the tests failed.

##MethodSource<a name="chapter-20"></a>

We can also use `@MethodSource` annotation to provide the input to our Parameterized Tests, using this annotation we will refer the method name which returns the values required for our tests as output.

```
@DisplayName("Method Source Case - Phone Number should match the required Format")
@ParameterizedTest
@MethodSource("phoneNumberList")
public void shouldTestPhoneNumberFormatUsingMethodSource(String phoneNumber) {
    contactManager.addContact("John", "Doe", phoneNumber);
    assertFalse(contactManager.getAllContacts().isEmpty());
    assertEquals(1, contactManager.getAllContacts().size());
}
 
private List<String> phoneNumberList() {
    return Arrays.asList("0123456789", "1234567890", "+0123456789");
}
```
In the above test, we declared a method called as `phoneNumberList()` which returns the required input values as a `List<String>`.

We passed the name of this method as the value to the `@MethodSource` annotation.

You can see the below output when you run the test.

![Method Source](https://i2.wp.com/programmingtechie.com/wp-content/uploads/2020/12/image-10.png?w=789&ssl=1)

##CsvSource<a name="chapter-21"></a>

You can create an inline CSV which contains the input for the test and reference that using the `@CsvSource` annotation.

Ex:
`@CsvSource({"1,0123456789", "2,1234567890","3,+0123456789"})`

```
@DisplayName("CSV Source Case - Phone Number should match the required Format")
@ParameterizedTest
@CsvSource({"0123456789", "1234567890","+0123456789"})
public void shouldTestPhoneNumberFormatUsingCSVSource(String phoneNumber) {
    contactManager.addContact("John", "Doe", phoneNumber);
    assertFalse(contactManager.getAllContacts().isEmpty());
    assertEquals(1, contactManager.getAllContacts().size());
}
```
##CsvFileSource<a name="chapter-22"></a>

You can also reference a CSV File by using the `@CsvFileSource `annotation.

Eg:
`@CsvFileSource(resources = "/data.csv")`

```
@DisplayName("CSV File Source Case - Phone Number should match the required Format")
@ParameterizedTest
@CsvFileSource(resources = "/data.csv")
public void shouldTestPhoneNumberFormatUsingCSVFileSource(String phoneNumber) {
    contactManager.addContact("John", "Doe", phoneNumber);
    assertFalse(contactManager.getAllContacts().isEmpty());
    assertEquals(1, contactManager.getAllContacts().size());
}
```

The contents of the csv looks like below:

```
0123456789
1234567890
+0123456789
```
Here is how the expected output looks like:

![CSV File Source](https://i2.wp.com/programmingtechie.com/wp-content/uploads/2020/12/image-12.png?w=838&ssl=1)

#Disabled Tests<a name="chapter-23"></a>

You can disable some tests from running by adding the @Disabled annotation.

```
@Test
@DisplayName("Test Should Be Disabled")
@Disabled
public void shouldBeDisabled() {
    throw new RuntimeException("Test Should Not be executed");
}
```
If you run the above test, you can see the output from Junit 5 that the test `shouldBeDisabled()` is `@Disabled`

![Disabled Test](https://i2.wp.com/programmingtechie.com/wp-content/uploads/2020/12/image-13.png?resize=1536%2C458&ssl=1)

#Nested Tests<a name="chapter-24"></a>

By now, you may have observed that our `ContactManagerTest` contains lots of test methods, we can organize these tests into Nested Tests using the `@Nested` annotation.

We are going to take a group of Tests and organize them into a seperate category of tests by creating a class and adding the `@Nested` annotation to it.

```
@Nested
class ParameterizedTests {
    @DisplayName("Phone Number should match the required Format")
    @ParameterizedTest
    @ValueSource(strings = {"0123456789", "1234567890", "+0123456789"})
    public void shouldTestPhoneNumberFormatUsingValueSource(String phoneNumber) {
        contactManager.addContact("John", "Doe", phoneNumber);
        assertFalse(contactManager.getAllContacts().isEmpty());
        assertEquals(1, contactManager.getAllContacts().size());
    }
 
    @DisplayName("CSV Source Case - Phone Number should match the required Format")
    @ParameterizedTest
    @CsvSource({"0123456789", "1234567890", "+0123456789"})
    public void shouldTestPhoneNumberFormatUsingCSVSource(String phoneNumber) {
        contactManager.addContact("John", "Doe", phoneNumber);
        assertFalse(contactManager.getAllContacts().isEmpty());
        assertEquals(1, contactManager.getAllContacts().size());
    }
 
    @DisplayName("CSV File Source Case - Phone Number should match the required Format")
    @ParameterizedTest
    @CsvFileSource(resources = "/data.csv")
    public void shouldTestPhoneNumberFormatUsingCSVFileSource(String phoneNumber) {
        contactManager.addContact("John", "Doe", phoneNumber);
        assertFalse(contactManager.getAllContacts().isEmpty());
        assertEquals(1, contactManager.getAllContacts().size());
    }
}
```
In the above example, you can see that we grouped all the Parameterized Tests together into a separate class.

If I run the tests you will see that the parameterized tests are displayed under a different node.

![Nested Tests](https://i2.wp.com/programmingtechie.com/wp-content/uploads/2020/12/image-14.png?w=1175&ssl=1)

#Running Tests using Maven Surefire Plugin<a name="chapter-25"></a>

Usually, you will run the tests when building the application, on a CI server. Maven is a build tool which helps us in automating the manual tasks associated with building the project.

We can use the [Maven Surefire Plugin](https://programmingtechie.com/2020/12/05/complete-maven-tutorial/#Maven_Surefire_Plugin) to execute the tests as part of the build, all you have to do is configure the plugin in the pom.xml file.

```
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.22.2</version>
</plugin>
```
You should also add the [Maven Compiler Plugin](https://programmingtechie.com/2020/12/05/complete-maven-tutorial/#Maven_Compile_Plugin) to compile our test classes as part of the build.

```
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.8.1</version>
    <configuration>
        <!--Use this only when using Java 9+-->
        <release>15</release>
        <!--
        Uncomment this and comment out <release> when using Java 8
        <source>1.8</source>
        <target>1.8</target>
        -->
    </configuration>
</plugin>
```
The **configuration** section compiles the test classes according to the target JDK version.

If you are using Java 9+ you should just use the **release** tag and if you are using Java 8, then you should uncomment the **source** and **target** section.

After adding these plugins, you can run the tests using the command `mvn clean test`
```
λ mvn clean test
 [INFO] Scanning for projects…
 [INFO]
 [INFO] --------------------< org.example:contact-manager >---------------------
 [INFO] Building contact-manager 1.0-SNAPSHOT
 [INFO] --------------------------------[ jar ]---------------------------------
 [INFO]
 [INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ contact-manager ---
 [INFO] Deleting F:\contact-manager\target
 [INFO]
 [INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ contact-manager ---
 [WARNING] Using platform encoding (Cp1252 actually) to copy filtered resources, i.e. build is platform dependent!
 [INFO] Copying 0 resource
 [INFO]
 [INFO] --- maven-compiler-plugin:3.8.1:compile (default-compile) @ contact-manager ---
 [INFO] Changes detected - recompiling the module!
 [WARNING] File encoding has not been set, using platform encoding Cp1252, i.e. build is platform dependent!
 [INFO] Compiling 2 source files to F:\contact-manager\target\classes
 [INFO]
 [INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ contact-manager ---
 [WARNING] Using platform encoding (Cp1252 actually) to copy filtered resources, i.e. build is platform dependent!
 [INFO] Copying 1 resource
 [INFO]
 [INFO] --- maven-compiler-plugin:3.8.1:testCompile (default-testCompile) @ contact-manager ---
 [INFO] Changes detected - recompiling the module!
 [WARNING] File encoding has not been set, using platform encoding Cp1252, i.e. build is platform dependent!
 [INFO] Compiling 1 source file to F:\contact-manager\target\test-classes
 [INFO]
 [INFO] --- maven-surefire-plugin:2.22.2:test (default-test) @ contact-manager ---
 [INFO]
 [INFO] -------------------------------------------------------
 [INFO]  T E S T S
 [INFO] -------------------------------------------------------
 [INFO] Running ContactManagerTest
 Should Print Before All Tests
 Instantiating Contact Manager
 Should Execute After Each Test
 Instantiating Contact Manager
 Should Execute After Each Test
 Instantiating Contact Manager
 Should Execute After Each Test
 Instantiating Contact Manager
 Should Execute After Each Test
 Instantiating Contact Manager
 Should Execute After Each Test
 Instantiating Contact Manager
 Should Execute After Each Test
 Instantiating Contact Manager
 Should Execute After Each Test
 Instantiating Contact Manager
 Should Execute After Each Test
 Instantiating Contact Manager
 Should Execute After Each Test
 Instantiating Contact Manager
 Should Execute After Each Test
 Instantiating Contact Manager
 Should Execute After Each Test
 Instantiating Contact Manager
 Should Execute After Each Test
 Instantiating Contact Manager
 Should Execute After Each Test
 Instantiating Contact Manager
 Should Execute After Each Test
 Instantiating Contact Manager
 Should Execute After Each Test
 Instantiating Contact Manager
 Should Execute After Each Test
 Instantiating Contact Manager
 Should Execute After Each Test
 Instantiating Contact Manager
 Should Execute After Each Test
 Instantiating Contact Manager
 Should Execute After Each Test
 Instantiating Contact Manager
 Should Execute After Each Test
 Instantiating Contact Manager
 Should Execute After Each Test
 Instantiating Contact Manager
 Should Execute After Each Test
 Should be executed at the end of the Test
 [WARNING] Tests run: 24, Failures: 0, Errors: 0, Skipped: 3, Time elapsed: 0.215 s - in ContactManagerTest
 [INFO]
 [INFO] Results:
 [INFO]
 [WARNING] Tests run: 24, Failures: 0, Errors: 0, Skipped: 3
 [INFO]
 [INFO] ------------------------------------------------------------------------
 [INFO] BUILD SUCCESS
 [INFO] ------------------------------------------------------------------------
 [INFO] Total time:  2.813 s
 [INFO] Finished at: 2020-12-26T00:41:57+01:00
 [INFO] ------------------------------------------------------------------------
```
#Conclusion<a name="chapter-26"></a>

So we reached to the end of the Junit 5 Complete Tutorial, I hope you learned something about Junit 5.

Please don’t forget to share this article with your friends and colleagues if they find it useful.

I will see you in the next article, until then Happy Coding Techies 🙂