36

How can I get name of the test method in JUnit 5?

Mahozad
  • 18,032
  • 13
  • 118
  • 133

4 Answers4

38

Declare a parameter of type TestInfo in your test method and JUnit will automatically supply an instance of that for the method:

@Test
void getTestInfo(TestInfo testInfo) { // Automatically injected
    System.out.println(testInfo.getDisplayName());
    System.out.println(testInfo.getTestMethod());
    System.out.println(testInfo.getTestClass());
    System.out.println(testInfo.getTags());
}

You can get test method name (and more) from the TestInfo instance as shown above.

Mahozad
  • 18,032
  • 13
  • 118
  • 133
  • 4
    This is lovely but if you have mildly complicated tests then you have to pass the testinfo around the method changes which makes them unnecessarily complicated. ``` @Test void test(TestInfo info) { complicatedValidation(info); } ``` – Michael McCallum Aug 01 '20 at 11:40
  • @MichaelMcCallum see my answer below. – zr0gravity7 Feb 08 '22 at 04:52
  • Remember that testInfo.getDisplayName() will return spaces, special characters and even emoticons. This was designed for IDES specifically. For a programatically approach it would be necessary to add some regex or use a custom name with @Display in each test. – Miguel Ortiz Aug 19 '22 at 14:44
26

In addition to what is written about injecting TestInfo to test method it is also possible to inject TestInfo to methods annotated with @BeforeEach and @AfterEach which might be useful sometimes:

@BeforeEach
void setUp(TestInfo testInfo) {
  log.info(String.format("test started: %s", testInfo.getDisplayName()));
}
@AfterEach
void tearDown(TestInfo testInfo) {
  log.info(String.format("test finished: %s", testInfo.getDisplayName()));
}
Kajzer
  • 2,138
  • 3
  • 32
  • 46
  • This was much more useful for the situation I was facing where we had a base test class that each of our other tests extended - assigning the TestInfo variable to an instance method here meant we only had to add our fix in one place! – Lorcan O'Neill Jun 10 '21 at 08:46
  • 1
    The seems to be the best and most clean solution I've found on this matter. – Kajzer Feb 27 '23 at 06:13
6

An alternative for having the test name globally available as was possible in JUnit 4 is to shim the functionality yourself in a setup method using the TestInfo interface.

From the JUnit documentation on "Dependency Injection for Constructors and Methods":

The TestInfo can then be used to retrieve information about the current container or test such as the display name, the test class, the test method, and associated tags.

Here we leverage the fact that the built-in resolvers will supply an instance of TestInfo corresponding to the current container or test as the value for parameters of type TestInfo to methods annotated as lifecycle hooks (here we use @BeforeEach).

import org.junit.jupiter.api.TestInfo;

public class MyTestClass {
  String displayName;

  @BeforeEach
  void setUp(TestInfo testInfo) {
    displayName = testInfo.getDisplayName();
    // ... the rest of your setup
  }
}

This for example enables you to reference the current test name in other non-test methods (such as various utility methods) without having to include the test name as a parameter to each function call from the initial test method to that utility method.

You can do the same for other information about the current container or test.

Seems like the only disadvantages are:

  • the instance variable cannot be made final, as it is set dynamically
  • may pollute your setup code

For reference, here is how the TestName-Rule might be implemented in JUnit 4:

public class MyTestClass {
  @Rule
  public final TestName name = new TestName();
}
zr0gravity7
  • 2,917
  • 1
  • 12
  • 33
0

The answers here already cover what the OP asked, but for completeness sake, I am adding a link here to a Baeldung article which covers this topic for both JUnit 5 and JUnit 4, in case someone stumbles upon this question while looking for how to get the test name in JUnit 4.

As already mentioned, for JUnit 5 one can utilize the TestInfo class, injecting an instance of it as a parameter to either your test method or to a method annotated with the @BeforeEach annotation. For JUnit 4, one would use a TestName instance annotated with the @Rule annotation. The article linked here also touches on handling parameterized tests.

Will
  • 3,500
  • 4
  • 30
  • 38