java - 检查 JUnit 扩展是否抛出特定异常

标签 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.");
        }
    }
}

现在我想测试我的扩展是否按预期工作。

@ExtendWith(DisallowUppercaseLetterAtBeginning.class)
class MyTest {

    @Test
    void validTest() {
    }

    @Test
    void TestShouldNotBeCalled() {
        fail("test should have failed before");
    }
}

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

最佳答案

另一种方法可能是使用新的 JUnit 5 - Jupiter 框架提供的工具。

我将我在 Eclipse Oxygen 上使用 Java 1.8 测试的代码放在下面。该代码缺乏优雅和简洁,但有望作为为您的元测试用例构建强大解决方案的基础。

请注意,这实际上是 JUnit 5 的测试方式,我建议您引用 the unit tests of the Jupiter engine on Github .

public final class DisallowUppercaseLetterAtBeginningTest { 
    @Test
    void testIt() {
        // Warning here: I checked the test container created below will
        // execute on the same thread as used for this test. We should remain
        // careful though, as the map used here is not thread-safe.
        final Map<String, TestExecutionResult> events = new HashMap<>();

        EngineExecutionListener listener = new EngineExecutionListener() {
            @Override
            public void executionFinished(TestDescriptor descriptor, TestExecutionResult result) {
                if (descriptor.isTest()) {
                    events.put(descriptor.getDisplayName(), result);
                }
                // skip class and container reports
            }

            @Override
            public void reportingEntryPublished(TestDescriptor testDescriptor, ReportEntry entry) {}
            @Override
            public void executionStarted(TestDescriptor testDescriptor) {}
            @Override
            public void executionSkipped(TestDescriptor testDescriptor, String reason) {}
            @Override
            public void dynamicTestRegistered(TestDescriptor testDescriptor) {}
        };

        // Build our test container and use Jupiter fluent API to launch our test. The following static imports are assumed:
        //
        // import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass
        // import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request

        JupiterTestEngine engine = new JupiterTestEngine();
        LauncherDiscoveryRequest request = request().selectors(selectClass(MyTest.class)).build();
        TestDescriptor td = engine.discover(request, UniqueId.forEngine(engine.getId())); 

        engine.execute(new ExecutionRequest(td, listener, request.getConfigurationParameters()));

        // Bunch of verbose assertions, should be refactored and simplified in real code.
        assertEquals(new HashSet<>(asList("validTest()", "TestShouldNotBeCalled()")), events.keySet());
        assertEquals(Status.SUCCESSFUL, events.get("validTest()").getStatus());
        assertEquals(Status.FAILED, events.get("TestShouldNotBeCalled()").getStatus());

        Throwable t = events.get("TestShouldNotBeCalled()").getThrowable().get();
        assertEquals(RuntimeException.class, t.getClass());
        assertEquals("test method names should start with lowercase.", t.getMessage());
}

虽然有点冗长,但这种方法的一个优点是它不需要在相同的 JUnit 容器中模拟和执行测试,因为稍后将用于实际单元测试。

通过一些清理,可以实现更具可读性的代码。同样,JUnit-Jupiter 资源可以成为很好的灵感来源。

关于java - 检查 JUnit 扩展是否抛出特定异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47237611/

相关文章:

java - 如何在 Android studio 中每 24 小时重置一次数据结构?

java - 如何为Azure Function TimerTrigger实现单元测试

java - 触发链接但不更改页面内容

java - Spring + hibernate : Initializing database with JUnit doesn't work

java - 使用 PowerMock 模拟链式方法调用

java - 快速将assertXY语句从JUnit4迁移到Junit5?

java - 使用 .contains 方法忽略大小写的选项?

java - (JUnitCore.runClasses) Java中的 'Main'类如何处理Junit文件?

Java JUnit 5 AssertAll 流

java - 使用 Gradle 执行单个 JUnit5 测试