I released five new sample lessons from my Test With Spring course: Introduction to Spock Framework

JUnit 5 Tutorial: Writing Our First Test Class

This blog post describes how we can write our first test class with JUnit 5. To be more specific, we will learn how we can create test classes, use setup and teardown methods, and write simple test methods with JUnit 5.

Let’s start by creating our first test class.

Creating Our First Test Class

A test class is just a normal Java class that is either public or package private. We can create our first test class by following these steps:

  1. Create a new package private class.
  2. Configure the display name of our test class by annotating it with the @DisplayName annotation. This is an optional step, but I recommend that we should do this because the @DisplayName annotation allows us to specify a custom display name that is used by our IDE and other build tools when they create or show test reports. In other words, we can replace a technical name with a sentence that describes the purpose of our test class.

After we have created our first test class, its source code looks as follows:

import org.junit.jupiter.api.DisplayName;

@DisplayName("JUnit 5 Example")
class JUnit5ExampleTest {
    
}
We can add the @DisplayName annotation to a test class or to a test method.

Additional Reading:

We have now created our first test class. Next, we will find out how we can use setup and teardown methods.

Using Setup and Teardown Methods

A test class can have four setup and teardown methods that must fulfill these two conditions:

  • These methods must not return anything. In other words, their return type must be void.
  • Setup and teardown methods cannot be private.

The supported setup and teardown methods are described in the following:

  • The method that is annotated with the @BeforeAll annotation must be static, and it is run once before any test method is run.
  • The method that is annotated with the @BeforeEach is invoked before each test method.
  • The method that is annotated with the @AfterEach annotation is invoked after each test method.
  • The method that is annotated with the @AfterAll annotation must be static, and it is run once after all test methods have been run.

Let’s add these methods to our test class. After we have added these setup and teardown methods to our test class, its source looks as follows:

import org.junit.jupiter.api.*;

@DisplayName("JUnit 5 Example")
class JUnit5ExampleTest {

    @BeforeAll
    static void beforeAll() {
        System.out.println("Before all test methods");
    }

    @BeforeEach
    void beforeEach() {
        System.out.println("Before each test method");
    }

    @AfterEach
    void afterEach() {
        System.out.println("After each test method");
    }

    @AfterAll
    static void afterAll() {
        System.out.println("After all test methods");
    }
}

There are three things which I want to point out:

  • We write information to System.out only because it’s the easiest way to demonstrate the invocation order of setup, teardown, and test methods.
  • All setup and teardown methods are inherited as long as they are not overridden. Also, the setup and teardown methods found from the superclasses are invoked before the setup and teardown methods which are found from the subclasses.
  • The methods that are annotated with the @BeforeAll and @AfterAll annotations must be static only if you create a new test instance for each test method (this is the default behavior of JUnit 5). However, it is also possible to use a setting that creates a new test instance for each test class. If you use the latter option, the methods annotated with the @BeforeAll and @AfterAll annotations don’t have to be static.

Additional Reading:

After we have added setup and teardown methods to our test class, we can finally write our first test methods. Let’s find out how we can do it.

Writing Our First Test Methods

A test method is a method that is not private or static, and it must not return anything. Every test method must be annotated with the @Test annotation. Also, we can override the display name of a test method by annotating it with the @DisplayName annotation.

Let’s add two test methods to our test class:

  1. The firstTest() method has a custom display name and it writes a unique string to System.out.
  2. The secondTest() method has a custom display name and it writes a unique string to System.out.

After we have written these two test methods, the source code of our test class looks as follows:

import org.junit.jupiter.api.*;

@DisplayName("JUnit 5 Example")
class JUnit5ExampleTest {

    @BeforeAll
    static void beforeAll() {
        System.out.println("Before all test methods");
    }

    @BeforeEach
    void beforeEach() {
        System.out.println("Before each test method");
    }

    @AfterEach
    void afterEach() {
        System.out.println("After each test method");
    }

    @AfterAll
    static void afterAll() {
        System.out.println("After all test methods");
    }

    @Test
    @DisplayName("First test")
    void firstTest() {
        System.out.println("First test method");
    }

    @Test
    @DisplayName("Second test")
    void secondTest() {
        System.out.println("Second test method");
    }
}
Again, I think that we should specify custom display names to our test methods because we can use real sentences instead of technical names.

Additional Reading:

We have just written our first test methods. Let’s see what happens when we run our unit tests.

Running Our Unit Tests

When we run our unit tests, we should see the following output:

Before all test methods
Before each test method
First test method
After each test method
Before each test method
Second test method
After each test method
After all test methods

This output proves that the setup, teardown, and test methods are run in the correct order. Let’s summarize what we learned from this blog post.

Summary

This blog post has taught us four things:

  • A test class is a normal Java class that is either public or package private.
  • Setup and teardown methods must not be private and they must not return anything.
  • A test method is a method that is not private and doesn’t return anything.
  • We should specify the display name of a test class and a test method because this allows us to replace technical names with sentences that make sense.

P.S. You can get the example application of this blog post from Github.

About the Author

Petri Kainulainen is passionate about software development and continuous improvement. He is specialized in software development with the Spring Framework and is the author of Spring Data book.

About Petri Kainulainen →

7 comments… add one
  • Hi Petri, thank you for the great introduction to jUnit. It’s clear and concise, and certainly very helpful to me as the beginner.

    If you don’t mind, let me draw your attention to this sentence in the post:
    “The methods annotated with the @BeforeAll or @AfterAll don’t have to be static. This doesn’t belong to…”
    Is there a mistake, shouldn’t these annotations be static?

    Reply
    • I apologize for being impolite in my previous comment and forgetting to sign myself :/
      Regards,
      Lada

      Reply
    • Hi,

      no worries. I don’t think that you were impolite at all. About your question:

      The methods that are annotated with the @BeforeAll and @AfterAll annotations must be static only if you create a new test instance for each test method (this is the default behavior of JUnit 5). However, it is also possible to use a setting that creates a new test instance for each test class. If you use the latter option, the methods annotated with the @BeforeAll and @AfterAll annotations don’t have to be static.

      I will update the post because the original sentence is indeed a bit confusing. Thank you for pointing this out!

      Reply
  • That was very unhelpful.Everybody knows JUnit4 and thus does not need to be reminded of the basics. What is needed instead is a commentary on the differences between JUnit4 and JUnit5.

    Reply
    • Hi Olivier,

      It seems that we have a bit different goals (and that’s fine). I want to write a tutorial for people who haven’t necessarily used JUnit 4. You (obviously) don’t need such tutorial. Instead, you could take a look at this blog post that explains how you can migrate from JUnit 4 to JUnit 5.

      By the way, thank you for pointing out that different people have different needs. I will remember this when I create content for people who are familiar with JUnit 4 and want to get started with JUnit 5.

      Reply
  • That was a nice intro of JUnit basics. I look forward to one or more posts where you handle all the new elements of JUnit 5.

    Reply
    • Hi,

      Thank you for your kind words. I really appreciate them. Also, the next posts of this tutorial will describe the new features of JUnit 5 such as nested tests, extensions, and so on.

      Reply

Leave a Comment