diff --git a/junit5/pom.xml b/junit5/pom.xml
index 9f06ebe6a5..6cc1405de8 100644
--- a/junit5/pom.xml
+++ b/junit5/pom.xml
@@ -21,6 +21,8 @@
1.8
5.0.0-M4
1.0.0-M4
+ 4.12.0-M4
+ 4.12
3.6.0
2.19.1
@@ -51,11 +53,40 @@
+
+
+ junit
+ junit
+ ${junit4.version}
+ test
+
+
+
+ org.junit.jupiter
+ junit-jupiter-api
+ ${junit.jupiter.version}
+ test
+
+
org.junit.jupiter
junit-jupiter-engine
${junit.jupiter.version}
test
+
+
+ org.junit.platform
+ junit-platform-runner
+ ${junit.platform.version}
+ test
+
+
+
\ No newline at end of file
diff --git a/junit5/src/test/java/com/baeldung/migration/junit4/AnnotationTestExampleTest.java b/junit5/src/test/java/com/baeldung/migration/junit4/AnnotationTestExampleTest.java
new file mode 100644
index 0000000000..fd7fd93d66
--- /dev/null
+++ b/junit5/src/test/java/com/baeldung/migration/junit4/AnnotationTestExampleTest.java
@@ -0,0 +1,23 @@
+package com.baeldung.migration.junit4;
+
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import com.baeldung.migration.junit4.categories.Annotations;
+import com.baeldung.migration.junit4.categories.JUnit4Tests;
+
+@Category(value = { Annotations.class, JUnit4Tests.class })
+public class AnnotationTestExampleTest {
+ @Test(expected = Exception.class)
+ public void shouldRaiseAnException() throws Exception {
+ throw new Exception("This is my expected exception");
+ }
+
+ @Test(timeout = 1)
+ @Ignore
+ public void shouldFailBecauseTimeout() throws InterruptedException {
+ Thread.sleep(10);
+ }
+
+}
diff --git a/junit5/src/test/java/com/baeldung/migration/junit4/AssertionsExampleTest.java b/junit5/src/test/java/com/baeldung/migration/junit4/AssertionsExampleTest.java
new file mode 100644
index 0000000000..ff2a05a8c4
--- /dev/null
+++ b/junit5/src/test/java/com/baeldung/migration/junit4/AssertionsExampleTest.java
@@ -0,0 +1,28 @@
+package com.baeldung.migration.junit4;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.Ignore;
+import org.junit.Test;
+
+public class AssertionsExampleTest {
+ @Test
+ @Ignore
+ public void shouldFailBecauseTheNumbersAreNotEqualld() {
+ assertEquals("Numbers are not equal!", 2, 3);
+ }
+
+ @Test
+ public void shouldAssertAllTheGroup() {
+ List list = Arrays.asList(1, 2, 3);
+ assertEquals("List is not incremental", list.get(0)
+ .intValue(), 1);
+ assertEquals("List is not incremental", list.get(1)
+ .intValue(), 2);
+ assertEquals("List is not incremental", list.get(2)
+ .intValue(), 3);
+ }
+}
diff --git a/junit5/src/test/java/com/baeldung/migration/junit4/RuleExampleTest.java b/junit5/src/test/java/com/baeldung/migration/junit4/RuleExampleTest.java
new file mode 100644
index 0000000000..10af6a9254
--- /dev/null
+++ b/junit5/src/test/java/com/baeldung/migration/junit4/RuleExampleTest.java
@@ -0,0 +1,18 @@
+package com.baeldung.migration.junit4;
+
+import org.junit.Rule;
+import org.junit.Test;
+
+import com.baeldung.migration.junit4.rules.TraceUnitTestRule;
+
+public class RuleExampleTest {
+
+ @Rule
+ public final TraceUnitTestRule traceRuleTests = new TraceUnitTestRule();
+
+ @Test
+ public void whenTracingTests() {
+ System.out.println("This is my test");
+ /*...*/
+ }
+}
diff --git a/junit5/src/test/java/com/baeldung/migration/junit4/categories/Annotations.java b/junit5/src/test/java/com/baeldung/migration/junit4/categories/Annotations.java
new file mode 100644
index 0000000000..a2b1b6bdd3
--- /dev/null
+++ b/junit5/src/test/java/com/baeldung/migration/junit4/categories/Annotations.java
@@ -0,0 +1,5 @@
+package com.baeldung.migration.junit4.categories;
+
+public interface Annotations {
+
+}
diff --git a/junit5/src/test/java/com/baeldung/migration/junit4/categories/JUnit4Tests.java b/junit5/src/test/java/com/baeldung/migration/junit4/categories/JUnit4Tests.java
new file mode 100644
index 0000000000..6af63d58ab
--- /dev/null
+++ b/junit5/src/test/java/com/baeldung/migration/junit4/categories/JUnit4Tests.java
@@ -0,0 +1,5 @@
+package com.baeldung.migration.junit4.categories;
+
+public interface JUnit4Tests {
+
+}
diff --git a/junit5/src/test/java/com/baeldung/migration/junit4/rules/TraceUnitTestRule.java b/junit5/src/test/java/com/baeldung/migration/junit4/rules/TraceUnitTestRule.java
new file mode 100644
index 0000000000..5c993f17fd
--- /dev/null
+++ b/junit5/src/test/java/com/baeldung/migration/junit4/rules/TraceUnitTestRule.java
@@ -0,0 +1,35 @@
+package com.baeldung.migration.junit4.rules;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runners.model.MultipleFailureException;
+import org.junit.runners.model.Statement;
+
+public class TraceUnitTestRule implements TestRule {
+
+ @Override
+ public Statement apply(Statement base, Description description) {
+
+ return new Statement() {
+ @Override
+ public void evaluate() throws Throwable {
+ List errors = new ArrayList();
+
+ System.out.println("Starting test ... " + description.getMethodName());
+ try {
+ base.evaluate();
+ } catch (Throwable e) {
+ errors.add(e);
+ } finally {
+ System.out.println("... test finished. " + description.getMethodName());
+ }
+
+ MultipleFailureException.assertEmpty(errors);
+ }
+ };
+ }
+
+}
diff --git a/junit5/src/test/java/com/baeldung/migration/junit5/AnnotationTestExampleTest.java b/junit5/src/test/java/com/baeldung/migration/junit5/AnnotationTestExampleTest.java
new file mode 100644
index 0000000000..07d8ae64e4
--- /dev/null
+++ b/junit5/src/test/java/com/baeldung/migration/junit5/AnnotationTestExampleTest.java
@@ -0,0 +1,28 @@
+package com.baeldung.migration.junit5;
+
+import java.time.Duration;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Tag;
+import org.junit.jupiter.api.Test;
+import org.junit.platform.runner.JUnitPlatform;
+import org.junit.runner.RunWith;
+
+@Tag("annotations")
+@Tag("junit5")
+@RunWith(JUnitPlatform.class)
+public class AnnotationTestExampleTest {
+ @Test
+ public void shouldRaiseAnException() throws Exception {
+ Assertions.assertThrows(Exception.class, () -> {
+ throw new Exception("This is my expected exception");
+ });
+ }
+
+ @Test
+ @Disabled
+ public void shouldFailBecauseTimeout() throws InterruptedException {
+ Assertions.assertTimeout(Duration.ofMillis(1), () -> Thread.sleep(10));
+ }
+}
diff --git a/junit5/src/test/java/com/baeldung/migration/junit5/AssertionsExampleTest.java b/junit5/src/test/java/com/baeldung/migration/junit5/AssertionsExampleTest.java
new file mode 100644
index 0000000000..642b7371de
--- /dev/null
+++ b/junit5/src/test/java/com/baeldung/migration/junit5/AssertionsExampleTest.java
@@ -0,0 +1,39 @@
+package com.baeldung.migration.junit5;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+import org.junit.platform.runner.JUnitPlatform;
+import org.junit.runner.RunWith;
+
+@RunWith(JUnitPlatform.class)
+public class AssertionsExampleTest {
+ @Test
+ @Disabled
+ public void shouldFailBecauseTheNumbersAreNotEqual() {
+ Assertions.assertEquals(2, 3, "Numbers are not equal!");
+ }
+
+ @Test
+ @Disabled
+ public void shouldFailBecauseItsNotTrue_overloading() {
+ Assertions.assertTrue(() -> {
+ return false;
+ }, () -> "It's not true!");
+ }
+
+ @Test
+ public void shouldAssertAllTheGroup() {
+ List list = Arrays.asList(1, 2, 3);
+
+ Assertions.assertAll("List is not incremental", () -> Assertions.assertEquals(list.get(0)
+ .intValue(), 1),
+ () -> Assertions.assertEquals(list.get(1)
+ .intValue(), 2),
+ () -> Assertions.assertEquals(list.get(2)
+ .intValue(), 3));
+ }
+}
diff --git a/junit5/src/test/java/com/baeldung/migration/junit5/RuleExampleTest.java b/junit5/src/test/java/com/baeldung/migration/junit5/RuleExampleTest.java
new file mode 100644
index 0000000000..a05360250b
--- /dev/null
+++ b/junit5/src/test/java/com/baeldung/migration/junit5/RuleExampleTest.java
@@ -0,0 +1,19 @@
+package com.baeldung.migration.junit5;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.platform.runner.JUnitPlatform;
+import org.junit.runner.RunWith;
+
+import com.baeldung.migration.junit5.extensions.TraceUnitExtension;
+
+@RunWith(JUnitPlatform.class)
+@ExtendWith(TraceUnitExtension.class)
+public class RuleExampleTest {
+
+ @Test
+ public void whenTracingTests() {
+ System.out.println("This is my test");
+ /*...*/
+ }
+}
diff --git a/junit5/src/test/java/com/baeldung/migration/junit5/extensions/TraceUnitExtension.java b/junit5/src/test/java/com/baeldung/migration/junit5/extensions/TraceUnitExtension.java
new file mode 100644
index 0000000000..104d311bc0
--- /dev/null
+++ b/junit5/src/test/java/com/baeldung/migration/junit5/extensions/TraceUnitExtension.java
@@ -0,0 +1,19 @@
+package com.baeldung.migration.junit5.extensions;
+
+import org.junit.jupiter.api.extension.AfterEachCallback;
+import org.junit.jupiter.api.extension.BeforeEachCallback;
+import org.junit.jupiter.api.extension.TestExtensionContext;
+
+public class TraceUnitExtension implements AfterEachCallback, BeforeEachCallback {
+
+ @Override
+ public void beforeEach(TestExtensionContext context) throws Exception {
+ System.out.println("Starting test ... " + context.getDisplayName());
+ }
+
+ @Override
+ public void afterEach(TestExtensionContext context) throws Exception {
+ System.out.println("... test finished. " + context.getDisplayName());
+ }
+
+}