There are many differences between JUnit 4 and 5, in terms of JUnit 5 having more capabilities and different ways of doing stuff.
But there are some very obvious differences between 4 and 5 in terms of: ignoring tests, running methods before and after methods and test classes, and exception asserting.
Explanation Video
Marking Tests as Ignored:
- JUnit 4 uses
@Ignore
- JUnit 5 uses
@Disabled
JUnit 4
@Ignore("because if this ran it would fail")
@Test
public void anIgnoredDisabledTest(){
Assert.assertFalse(true);
}
JUnit 5
@Disabled("because if this ran it would fail")
@Test
public void anIgnoredDisabledTest(){
Assertions.assertFalse(true);
}
Assertions are statically accessed from:
- JUnit 4 uses
Assert.
- JUnit 5 uses
Assertions.
JUnit 4
@Test
public void aTestMethodAssertingTrue(){
Assert.assertTrue(true);
}
JUnit 5
@Test
public void aTestMethodAssertingTrue(){
Assertions.assertTrue(true);
}
Assertion message position differs:
- JUnit 4 assertion messages are the first argument
- JUnit 5 assertion messages are the last argument
JUnit 4
@Test
public void aTestMethodAssertingWithMessage(){
String expected = "bob";
Assert.assertEquals("Because we always expect bob", expected, "bob");
}
JUnit 5
@Test
public void aTestMethodAssertingWithMessage(){
String expected = "bob";
Assertions.assertEquals(expected, "bob", "Because we always expect bob");
}
Annotations for running code before and after each method:
- JUnit 4 uses
@Before
, and@After
- JUnit 5 uses
@BeforeEach
, and@AfterEach
JUnit 4
@Before
public void runsBeforeEveryMethod(){
System.out.println("Running a Test Method");
}
@After
public void runsAfterEveryMethod(){
System.out.println("Finished Running a Test Method");
}
JUnit 5
@BeforeEach
public void runsBeforeEveryMethod(){
System.out.println("Running a Test Method");
}
@AfterEach
public void runsAfterEveryMethod(){
System.out.println("Finished Running a Test Method");
}
Annotations for running code before and after each class:
- JUnit 4 uses
@BeforeClass
, and@AfterClass
- JUnit 5 uses
@BeforeAll
, and@AfterAll
JUnit 4
@BeforeClass
public static void runsBeforeEverything(){
System.out.println("Running a Test Class");
}
@AfterClass
public static void runsAfterEverything(){
System.out.println("Finished Running a Test Class");
}
JUnit 5
@BeforeAll
public static void runsBeforeEverything(){
System.out.println("Running a Test Class");
}
@AfterAll
public static void runsAfterEverything(){
System.out.println("Finished Running a Test Class");
}
By default the methods need to be static
in both JUnit 4 and 5, but in v5 we
can annotate the class to avoid need to make the All
methods static:
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
Checking that an exception is thrown:
- JUnit 4 uses
@Test(expected = InterruptedException.class)
- JUnit 5 uses an assertion with the code in a closure lambda expression, which allows additional assertions to be made on the exception
Exception exception = Assertions.assertThrows(RuntimeException.class, () -> {
throw new NullPointerException(
"We interrupt this test to throw an runtime exception");
});
JUnit 4
@Test(expected = IOException.class)
public void shouldThrowAnCheckedException() throws IOException {
throw new IOException(
"We interrupt this test to throw an checked exception");
}
@Test(expected = NullPointerException.class)
public void shouldThrowAnRuntimeException(){
throw new NullPointerException(
"We interrupt this test to throw an runtime exception");
}
JUnit 5
@Test
public void shouldThrowAnCheckedException(){
Exception exception = Assertions.assertThrows(IOException.class, () -> {
throw new IOException(
"We interrupt this test to throw an checked exception");
});
// can continue to do more assertions on the exception
System.out.println(exception.getMessage());
Assertions.assertEquals(
"We interrupt this test to throw an checked exception",
exception.getMessage());
}
@Test
public void shouldThrowAnRuntimeException(){
Exception exception = Assertions.assertThrows(RuntimeException.class, () -> {
throw new NullPointerException(
"We interrupt this test to throw an runtime exception");
});
// can continue to do more assertions on the exception
System.out.println(exception.getMessage());
Assertions.assertEquals("We interrupt this test to throw an runtime exception",
exception.getMessage());
}
Note: from JUnit 4.13 it is possible to use
assertThrows
in Junit 4 as well.
Also Note: JUnit @Rule for exception testing was deprecated in v 4.13
https://github.com/junit-team/junit4/wiki/Exception-testing#expectedexception-rule
@Rule public ExpectedException expected = ExpectedException.none(); @Test public void failsWithException(){ expected.expect(RuntimeException.class); expected.expectMessage("catch me"); throw new RuntimeException("catch me"); }
Supporting Source Code
You can find the supporting source code for this over at:
And specifically: