Course – LS – All

Get started with Spring and Spring Boot, through the Learn Spring course:

>> CHECK OUT THE COURSE

1. Overview

In this tutorial, we’ll show how to run JUnit tests directly from Java code – there are scenarios where this option comes in handy.

If you are new to JUnit, or if you want to upgrade to JUnit 5, you can check some of many tutorials we have on the topic.

2. Maven Dependencies

We’ll need a couple of basic dependencies to run both JUnit 4 and JUnit 5 tests:

<dependencies>
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-engine</artifactId>
        <version>5.9.2</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.junit.platform</groupId>
        <artifactId>junit-platform-launcher</artifactId>
        <version>1.2.0</version>
    </dependency>
</dependencies>

// for JUnit 4
<dependency> 
    <groupId>junit</groupId> 
    <artifactId>junit</artifactId> 
    <version>4.12</version> 
    <scope>test</scope> 
</dependency>

The latest versions of JUnit 4, JUnit 5, and JUnit Platform Launcher can be found on Maven Central.

3. Running JUnit 4 Tests

3.1. Test Scenario

For both JUnit 4 and JUnit 5, we’ll set up a few “placeholder” test classes which will be enough to demonstrate our examples:

public class FirstUnitTest {

    @Test
    public void whenThis_thenThat() {
        assertTrue(true);
    }

    @Test
    public void whenSomething_thenSomething() {
        assertTrue(true);
    }

    @Test
    public void whenSomethingElse_thenSomethingElse() {
        assertTrue(true);
    }
}
public class SecondUnitTest {

    @Test
    public void whenSomething_thenSomething() {
        assertTrue(true);
    }

    @Test
    public void whensomethingElse_thenSomethingElse() {
        assertTrue(true);
    }
}

When using JUnit 4, we create test classes adding @Test annotation to every test method.

We can also add other useful annotations, such as @Before or @After, but that’s not in the scope of this tutorial.

3.2. Running a Single Test Class

To run JUnit tests from Java code, we can use the JUnitCore class (with an addition of TextListener class, used to display the output in System.out):

JUnitCore junit = new JUnitCore();
junit.addListener(new TextListener(System.out));
junit.run(FirstUnitTest.class);

On the console, we’ll see a very simple message indicating successful tests:

Running one test class:
..
Time: 0.019
OK (2 tests)

3.3. Running Multiple Test Classes

If we want to specify multiple test classes with JUnit 4, we can use the same code as for a single class, and simply add the additional classes:

JUnitCore junit = new JUnitCore();
junit.addListener(new TextListener(System.out));

Result result = junit.run(
  FirstUnitTest.class, 
  SecondUnitTest.class);

resultReport(result);

Note that the result is stored in an instance of JUnit’s Result class, which we’re printing out using a simple utility method:

public static void resultReport(Result result) {
    System.out.println("Finished. Result: Failures: " +
      result.getFailureCount() + ". Ignored: " +
      result.getIgnoreCount() + ". Tests run: " +
      result.getRunCount() + ". Time: " +
      result.getRunTime() + "ms.");
}

3.4. Running a Test Suite

If we need to group some test classes in order to run them, we can create a TestSuite. This is just an empty class where we specify all classes using JUnit annotations:

@RunWith(Suite.class)
@Suite.SuiteClasses({
  FirstUnitTest.class,
  SecondUnitTest.class
})
public class MyTestSuite {
}

To run these tests, we’ll again use the same code as before:

JUnitCore junit = new JUnitCore();
junit.addListener(new TextListener(System.out));
Result result = junit.run(MyTestSuite.class);
resultReport(result);

3.5. Running Repeated Tests

One of the interesting features of JUnit is that we can repeat tests by creating instances of RepeatedTest. This can be really helpful when we’re testing random values, or for performance checks.

In the next example, we’ll run the tests from MergeListsTest five times:

Test test = new JUnit4TestAdapter(FirstUnitTest.class);
RepeatedTest repeatedTest = new RepeatedTest(test, 5);

JUnitCore junit = new JUnitCore();
junit.addListener(new TextListener(System.out));

junit.run(repeatedTest);

Here, we’re using JUnit4TestAdapter as a wrapper for our test class.

We can even create suites programmatically, applying repeated testing:

TestSuite mySuite = new ActiveTestSuite();

JUnitCore junit = new JUnitCore();
junit.addListener(new TextListener(System.out));

mySuite.addTest(new RepeatedTest(new JUnit4TestAdapter(FirstUnitTest.class), 5));
mySuite.addTest(new RepeatedTest(new JUnit4TestAdapter(SecondUnitTest.class), 3));

junit.run(mySuite);

4. Running JUnit 5 Tests

4.1. Test Scenario

With JUnit 5, we’ll use the same sample test classes as for the previous demo – FirstUnitTest and SecondUnitTest, with some minor differences due to a different version of JUnit framework, like the package for @Test and assertion methods.

4.2. Running Single Test Class

To run JUnit 5 tests from Java code, we’ll set up an instance of LauncherDiscoveryRequest. It uses a builder class where we must set package selectors and testing class name filters, to get all test classes that we want to run.

This request is then associated with a launcher and, before executing the tests, we’ll also set up a test plan and an execution listener.

Both of these will offer information about the tests to be executed and of the results:

public class RunJUnit5TestsFromJava {
    SummaryGeneratingListener listener = new SummaryGeneratingListener();

    public void runOne() {
        LauncherDiscoveryRequest request = LauncherDiscoveryRequestBuilder.request()
          .selectors(selectClass(FirstUnitTest.class))
          .build();
        Launcher launcher = LauncherFactory.create();
        TestPlan testPlan = launcher.discover(request);
        launcher.registerTestExecutionListeners(listener);
        launcher.execute(request);
    }
    // main method...
}

4.3. Running Multiple Test Classes

We can set selectors and filters to the request to run multiple test classes.

Let’s see how we can set package selectors and testing class name filters, to get all test classes that we want to run:

public void runAll() {
    LauncherDiscoveryRequest request = LauncherDiscoveryRequestBuilder.request()
      .selectors(selectPackage("com.baeldung.junit5.runfromjava"))
      .filters(includeClassNamePatterns(".*Test"))
      .build();
    Launcher launcher = LauncherFactory.create();
    TestPlan testPlan = launcher.discover(request);
    launcher.registerTestExecutionListeners(listener);
    launcher.execute(request);
}

4.4. Test Output

In the main() method, we call our class, and we also use the listener to get the result details. This time the result is stored as a TestExecutionSummary.

The simplest way to extract its info merely is by printing to a console output stream:

public static void main(String[] args) {
    RunJUnit5TestsFromJava runner = new RunJUnit5TestsFromJava();
    runner.runAll();

    TestExecutionSummary summary = runner.listener.getSummary();
    summary.printTo(new PrintWriter(System.out));
}

This will give us the details of our test run:

Test run finished after 177 ms
[         7 containers found      ]
[         0 containers skipped    ]
[         7 containers started    ]
[         0 containers aborted    ]
[         7 containers successful ]
[         0 containers failed     ]
[        10 tests found           ]
[         0 tests skipped         ]
[        10 tests started         ]
[         0 tests aborted         ]
[        10 tests successful      ]
[         0 tests failed          ]

5. Conclusion

In this article, we’ve shown how to run JUnit tests programmatically from Java code, covering JUnit 4 as well as the recent JUnit 5 version of this testing framework.

As always, the implementation of the examples shown here is available over on GitHub for both the JUnit 5 examples, as well as JUnit 4.

Course – LS – All

Get started with Spring and Spring Boot, through the Learn Spring course:

>> CHECK OUT THE COURSE
res – REST with Spring (eBook) (everywhere)
Comments are open for 30 days after publishing a post. For any issues past this date, use the Contact form on the site.