JUnit5 — Key Features

Anshul Mathur
TestVagrant
Published in
5 min readJun 10, 2020

Unit testing is unarguably an intrinsic component of the software delivery chain. Early invocation, fast feedback and high code coverage are major advantages of unit testing approach enabling robust app development. Agile teams working on different product modules in parallel rely substantially on writing exhaustive unit tests & getting them to use in build pipelines.

Some of the binding principles of unit testing include:

  1. Writing independent tests
  2. Having maximum code coverage(~100% in most cases)
  3. Using mock objects for third party dependencies(databases, services etc.)
  4. Keeping execution time to a minimum(achieved through crisp tests and parallel execution)
  5. Executing tests before deploying builds on the test environment(s)

….. and a few more.

Implementing these principles need relevant unit testing tools & libraries. Depending upon the choice of programming language, engineering teams opt for a variety of unit testing tools. In this blog, we’ll focus on one such tool and its evolution known as JUnit — a popular & highly efficient java based unit testing library.

JUnit 4 — Introduction & benefits

JUnit is an open-source unit testing framework that has been a popular choice for long amongst developers writing unit tests in Java. JUnit provides a lot of benefits including:

  1. Enables implementing test-driven development(TDD)
  2. Allows writing & running independent tests — each test execution happens on a different test class instance, thus avoiding any resource conflicts
  3. Provides a good validation library for comparisons
  4. Easy integration with various build tools like Maven, Gradle, Ant etc.
  5. Supported by all popular IDEs

JUnit 4 was launched back in 2006. With multiple minor releases done for JUnit 4 over some time, the library remained competitive and allowed developers to carry out a good amount of unit testing in conjunction with development.

However, a major reason for developers to look beyond JUnit 4 is the fact that it didn’t use advanced java concepts added in JDK 8 and above (like lambda expressions). And guess what? Entered JUnit 5! It provides more versatility and advanced java features out of the box!

JUnit 5 — the modern day unit testing tool

JUnit 5 was released in late 2017. The minimum requirement to use it is JDK 8. This version of JUnit is a combination of 3 projects :

  1. JUnit Platform: The TestEngine that provides execution runtime for JUnit tests
  2. JUnit Jupiter: The combination of libraries allowing implementation of advanced testing features
  3. JUnit Vintage: The TestEngine for supporting JUnit 3 and JUnit 4 tests

With JUnit 5, a lot of modifications & new features were introduced for making unit testing even more comprehensive and fast. In the next section, let’s look at some of the interesting additions to this library.

Writing JUnit 5 tests — Major Features

To begin, here are the required project dependencies for JUnit 5(all annotations used for demonstration in this blog are provided through these libraries — nothing beyond) :

Maven dependencies for JUnit 5, Gradle equivalents are also available.

Feature 1: Parameterising Test Methods

Creating a parameterized test has become possible in JUnit 5 using annotation @ParameterizedTest. It allows developers to run a test against different data sets(pretty similar to how TestNG’s data provider concept works)

Use case 1: Using @ValueSource annotation to provide primitive data types

Value source annotation allows passing all primitive types and executes the test as many times as the number of parameters.

Running this test shows 2 entries in the report — identified by index and argument value

Use case 2: Using @MethodSource annotation to provide a stream of objects

Feature 2: Richer assertion library

  1. Stacking assertions together: assertAll method

Notice how a lambda expression is used to stack multiple assertions together.

2. Asserting arrays directly: assertArrayEquals method

When array elements are not the same(or are indifferent order), here’s how assertion error is logged :

3. Assertions based on a time limit: assertTimeoutPreemptively method

The outer assertion would fail with a timeout exception if assertion it wraps up doesn’t give a result within a specified time

Feature 3: Assumptions

JUnit 5 introduced the concept of making assumptions to reduce the number of failures that were caused due to issues with test setup itself. Let’s look at an example:

Runner understand the assumption as a pre-requisite to running the test further

The assertion would only be invoked if the assumption passes — else the test would be marked as aborted. If assumption fails, here’s what the output looks like

Feature 4: Nested Tests

Grouping tests together has become possible in JUnit 5 using the @Nested annotation. This annotation allows the inclusion of inner classes & the tests within it to be executed with the main test class.

Having multiple tests inside an inner class and nesting them together inside the main test class

Feature 5: TestInstance annotation

Previously, all JUnit tests used to run in different test class instances which restricted sharing of class level variables between test methods.

However, JUnit 5 provides @TestInstance annotation that allows developers to design tests wherein resource sharing is possible. With this annotation, developers can choose to create a single instance of the test class for running all test methods or can continue using the vintage behaviour

Lifecycle.PER_METHOD is the other option to keep the older behaviour intact

Feature 6: Repetition of Tests

Running the same test with multiple iterations is now possible without any explicit looping — using @RepeatestTest annotation.

The placeholders are provided by JUnit itself for better identification of each iteration

Executing the above test would give a result that looks like :

Conclusion

What we explored were few of the major enhancements done in JUnit 5 release. With steady evolution of JUnit 4 over a year and such subtle transformations emerging in JUnit 5, this tool has been able to keep up with the pace of development.

There are many other features that JUnit 5 is bundled with — I’d encourage all readers to go through its official documentation. Go ahead and try it out!

Happy testing!

--

--