检查JUnit Extension是否抛出特定的Exception

Rol*_*der 5 java junit junit5 junit5-extension-model

假设我开发了一个扩展,它不允许测试方法名称以大写字符开头.

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.");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

现在我想测试我的扩展按预期工作.

@ExtendWith(DisallowUppercaseLetterAtBeginning.class)
class MyTest {

    @Test
    void validTest() {
    }

    @Test
    void TestShouldNotBeCalled() {
        fail("test should have failed before");
    }
}
Run Code Online (Sandbox Code Playgroud)

如何编写测试以验证执行第二个方法的尝试是否会抛出带有特定消息的RuntimeException?

Rol*_*der 1

在尝试了答案中的解决方案和评论中链接的问题后,我最终得到了使用 JUnit 平台启动器的解决方案。

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");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

JUnit 本身不会运行,MyTest因为它是一个没有@Nested. 因此在构建过程中不会出现失败的测试。

更新

JUnit 本身不会运行,MyTest因为它是一个没有@Nested. 因此在构建过程中不会出现失败的测试。

这并不完全正确。JUnit 本身也会运行MyTest,例如,如果在 IDE 或 Gradle 构建中启动“运行所有测试”。

之所以MyTest没有执行是因为我用的是Maven,并且用mvn test. Maven 使用 Maven Surefire 插件来执行测试。该插件有一个默认配置排除所有嵌套类,例如MyTest.

另请参阅有关“通过 Maven 从内部类运行测试”的答案以及评论中的链接问题。