If you want to learn how you can work smarter and save time when you are writing tests with JUnit 5, you should take a look at my Introduction to JUnit 5 course. It has 24 lessons, 47 exercises, and 13 quizzes.
This blog post describes how we can write our first test class with JUnit 5. After we have finished this blog post, we:
- Can create test classes with JUnit 5.
- Know how we can use setup and teardown methods.
- Understand how we can 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 a normal Java class that is either public
or package private. We can create our first test class by following these steps:
- Create a new package private class.
- Configure the display name of our test class by annotating it with the
@DisplayName
annotation. This is an optional step, but I think that we should always use the@DisplayName
annotation because it allows us to specify a custom display name that's 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 { }
@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's annotated with the
@BeforeAll
annotation must bestatic
, and it's run once before the test methods are run. - The method that's annotated with the
@BeforeEach
annotation is invoked before each test method. - The method that's annotated with the
@AfterEach
annotation is invoked after each test method. - The method that's annotated with the
@AfterAll
annotation must bestatic
, and it's 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"); } }
- 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 which are annotated with the
@BeforeAll
and@AfterAll
annotations must bestatic
only if you create a new test instance for each test method (this is the default behavior of JUnit 5). However, it's 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 bestatic
.
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 fulfills these three requirements:
- A test method isn't
private
orstatic
- A test method must not return anything. In other words, its return type must be
void
. - A test method must be annotated with the
@Test
annotation.
@DisplayName
annotation.Let's add two test methods to our test class:
- The
firstTest()
method has a custom display name and it writes a unique string toSystem.out
. - The
secondTest()
method has a custom display name and it writes a unique string toSystem.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"); } }
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 isn't
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.
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?
I apologize for being impolite in my previous comment and forgetting to sign myself :/
Regards,
Lada
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 bestatic
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 bestatic
.I will update the post because the original sentence is indeed a bit confusing. Thank you for pointing this out!
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.
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.
Thank you for this comprehensive and quick approach of JUnit. Some people indeed need a 'from scratch' presentation.
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.
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.