JUnit 5 vs JUnit 4

JUnit 5 aims to adapt the Java 8 style of coding and to be more robust and flexible than JUnit 4. In this post, JUnit 5 vs JUnit 4, we will focus on some major differences between JUnit 4 and JUnit 5.

1. Different Annotations

Most of the annotations in both versions are the same, but a few differ. Here is a quick comparison.

Feature
JUnit 4
Junit 5
Declare a test method
@Test
@Test
Execute before all test methods in the current class
@BeforeClass
Execute after all test methods in the current class
@AfterClass
Execute before each test method
@Before
Execute after each test method
@After
Disable a test method/class
@Ignore
Test factory for dynamic tests
NA
@TestFactory
Nested tests
NA
@Nested
Tagging and filtering
@Category
Register custom extensions
NA
@ExtendWith

2. More differences between JUnit 5 and JUnit 4

2.1. Architecture

JUnit 4 has everything bundled into a single jar file.

JUnit 5 is composed of 3 sub-projects i.e. JUnit Platform, JUnit Jupiter and JUnit Vintage.

  • JUnit Platform: It defines the TestEngine API for developing new testing frameworks that run on the platform.
  • JUnit Jupiter: It has all new JUnit annotations and TestEngine implementation to run tests written with these annotations.
  • JUnit Vintage: To support running JUnit 3 and JUnit 4 written tests on the JUnit 5 platform.

2.2. Required JDK Version

Junit 4 requires Java 5 or higher.

Junit 5 requires Java 8 or higher.

2.3. Assertions

In Junit 4, org.junit.Assert has all assert methods to validate expected and resulting outcomes.
They accept extra parameters for error messages as the FIRST argument in the method signature. e.g.

public static void assertEquals(long expected, long actual)
public static void assertEquals(String message, long expected, long actual)

In JUnit 5, org.junit.jupiter.Assertions contain most of assert() methods including additional assertThrows() and assertAll() methods.
JUnit 5 assertions methods also have overloaded methods to support parsing error messages to be printed in case test fails e.g.

public static void assertEquals(long expected, long actual)
public static void assertEquals(long expected, long actual, String message)
public static void assertEquals(long expected, long actual, Supplier messageSupplier)

2.4. Assumptions

In Junit 4, org.junit.Assume contains methods for stating assumptions about the conditions in which a test is meaningful. It has the following five methods:

  1. assumeFalse()
  2. assumeNoException()
  3. assumeNotNull()
  4. assumeThat()
  5. assumeTrue()

In Junit 5, org.junit.jupiter.api.Assumptions contain methods for stating assumptions about the conditions in which a test is meaningful. It has the following three methods:

  1. assumeFalse()
  2. assumingThat​()
  3. assumeTrue()

2.5. Tagging and Filtering

In Junit 4, @category annotation is used.

In Junit 5, @tag annotation is used.

2.6. Test Suites

In Junit 4, @RunWith and @Suite annotation. e.g.

import org.junit.runner.RunWith;
import org.junit.runners.Suite;

@RunWith(Suite.class)
@Suite.SuiteClasses({
        ExceptionTest.class,
        TimeoutTest.class
})
public class JUnit4Example
{
}

In Junit 5, @Suite, @SelectPackages and @SelectClasses e.g.

import org.junit.platform.runner.JUnitPlatform;
import org.junit.platform.suite.api.SelectPackages;
import org.junit.runner.RunWith;

@Suite
@SelectPackages("com.howtodoinjava.junit5.examples")
public class JUnit5Example
{
}

2.7. Non-public Test Methods are Allowed

  • JUnit 5 test classes and test methods are not required to be public. We can now make them package protected.
    JUnit internally uses reflection to find test classes and test methods. Reflection can discover them even if they have limited visibility so there is no need for them to be public.
  • JUnit test classes also can have non-public constructors. They can even have arguments. It means having a public no-args constructor is not mandatory in JUnit 5.
class AppTest {

    private AppTest(TestInfo testInfo) {
        System.out.println("Working on test " + testInfo.getDisplayName());
    }

  @Test
  void test(){
        assertTrue(true);
    }

}

2.8. 3rd Party Integration

In Junit 4, there is no integration support for 3rd party plugins and IDEs. They have to rely on reflection.

JUnit 5 has a dedicated sub-project for this purpose i.e. JUnit Platform. It defines the TestEngine API for developing a testing framework that runs on the platform.

Happy Learning !!

Was this post helpful?

Join 7000+ Awesome Developers

Get the latest updates from industry, awesome resources, blog updates and much more.

* We do not spam !!

8 thoughts on “JUnit 5 vs JUnit 4”

  1. If you are using paramertized tests in Junit4 the test data is loaded before the @BeforeClass method is called, in JUnit5 it’s the other way round – @BeforeAll then the test method

    Reply
  2. One missing note about annotations, @Rule.
    For example migration of springboot tests with rest documentation needs remove this rule:

    @Rule
    public final JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation();

    And annotate test class with:

    @ExtendWith(RestDocumentationExtension.class)

    Reply
    • Could you please suggest how to replace this rule in Junit5 test case?
      @Rule
      public EmbeddedActiveMQBroker broker = new EmbeddedActiveMQBroker();

      Reply

Leave a Comment

HowToDoInJava

A blog about Java and related technologies, the best practices, algorithms, and interview questions.