Suppose I develop an extension which disallows test method names to start with an uppercase character.
public class DisallowUppercaseLetterAtBeginning implements BeforeEachCallback {
@Override
public void beforeEach(ExtensionContext context) {
char c = context.getRequiredTestMethod().getName().charAt(0);
if (Character.isUpperCase(c)) {
throw new RuntimeException("test method names should start with lowercase.");
}
}
}
Now I want to test that my extension works as expected.
@ExtendWith(DisallowUppercaseLetterAtBeginning.class)
class MyTest {
@Test
void validTest() {
}
@Test
void TestShouldNotBeCalled() {
fail("test should have failed before");
}
}
How can I write a test to verify that the attempt to execute the second method throws a RuntimeException with a specific message?
After trying the solutions in the answers and the question linked in the comments, I ended up with a solution using the JUnit Platform Launcher.
class DisallowUppercaseLetterAtBeginningTest {
@Test
void should_succeed_if_method_name_starts_with_lower_case() {
TestExecutionSummary summary = runTestMethod(MyTest.class, "validTest");
assertThat(summary.getTestsSucceededCount()).isEqualTo(1);
}
@Test
void should_fail_if_method_name_starts_with_upper_case() {
TestExecutionSummary summary = runTestMethod(MyTest.class, "InvalidTest");
assertThat(summary.getTestsFailedCount()).isEqualTo(1);
assertThat(summary.getFailures().get(0).getException())
.isInstanceOf(RuntimeException.class)
.hasMessage("test method names should start with lowercase.");
}
private TestExecutionSummary runTestMethod(Class<?> testClass, String methodName) {
SummaryGeneratingListener listener = new SummaryGeneratingListener();
LauncherDiscoveryRequest request = request().selectors(selectMethod(testClass, methodName)).build();
LauncherFactory.create().execute(request, listener);
return listener.getSummary();
}
@ExtendWith(DisallowUppercaseLetterAtBeginning.class)
static class MyTest {
@Test
void validTest() {
}
@Test
void InvalidTest() {
fail("test should have failed before");
}
}
}
JUnit itself will not run MyTest
because it is an inner class without @Nested
. So there are no failing tests during the build process.
JUnit itself will not run
MyTest
because it is an inner class without@Nested
. So there are no failing tests during the build process.
This is not completly correct. JUnit itself would also run MyTest
, e.g. if "Run All Tests" is started within the IDE or within a Gradle build.
The reason why MyTest
was not executed is because I used Maven and I tested it with mvn test
. Maven uses the Maven Surefire Plugin to execute tests. This plugin has a default configuration which excludes all nested classes like MyTest
.
See also this answer about "Run tests from inner classes via Maven" and the linked issues in the comments.