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

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

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 Maptest()) {
                    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资源可以成为灵感的重要来源.

相关文章

最近看了一下学习资料,感觉进制转换其实还是挺有意思的,尤...
/*HashSet 基本操作 * --set:元素是无序的,存入和取出顺序不...
/*list 基本操作 * * List a=new List(); * 增 * a.add(inde...
/* * 内部类 * */ 1 class OutClass{ 2 //定义外部类的成员变...
集合的操作Iterator、Collection、Set和HashSet关系Iterator...
接口中常量的修饰关键字:public,static,final(常量)函数...