【问题标题】:JUnit5 - is there any reliable way to get class of an executed testJUnit5 - 有没有可靠的方法来获得执行测试的类
【发布时间】:2017-03-14 08:27:07
【问题描述】:

我正在编写一个测试执行监听器。 Junit5 框架的一个小扩展。在运行具有TestIdentifierTestPlan 的特定测试时,有必要知道使用了什么类。

((MethodSource) id.getSource().get()).getClassName(); 

只给出一个测试被声明的类。 但是,这并不意味着它是从声明的类中运行的。

例如,可以从子类运行测试。

TestIdentifier#getUniqueId() 的解析结果 可能因情况而异 (junit4单次测试,junit5单次测试,junit5动态测试,junit4参数化测试等)

目前我没有发现任何可能这样做。

是否有任何可靠的方法来获得执行测试的类?

【问题讨论】:

  • TestInfo 用作3.9. Dependency Injection 中所述的参数可能会有所帮助。至少,有一个可选的getTestClass() 访问器。
  • 不幸的是,我认为情况并非如此。 TestExecutionListener 不知道作为参数传递给测试方法的内容。此外,这意味着每个测试方法都必须将 TestInfo 作为参数 - 并非总是如此
  • 我可能没有完全按照您的要求。在 JUnit4(我假设为 5)中,我们使用了几个 @Rule 注释(一个是 TestWatcher(),另一个只是 TestName())来解决您的部分问题。我们还使用了 Thread.currentThread().getStackTrace() 并从堆栈跟踪中发出了正确的信息。
  • JUnit5 中的TestExecutionListener 是一种监听器,用于获取测试开始、测试结束、测试跳过的事件(通知)。一旦连接到测试执行框架,它就可以监听 any 测试的结果 - 任何测试开始、完成或可以跳过。因此 Junit4 和 Junit5 测试也是这个过程的一个可能部分。 Thread.currentThread().getStackTrace() 是个好主意。但是不会从已执行的测试方法调用 TestExecutionListener 通知 - 因为在此堆栈跟踪中找不到结果类。调用测试,然后发送通知。

标签: java junit5


【解决方案1】:

testPlanExecutionStarted 中保存对TestPlan 的引用,并使用testPlan.getParent(testIdentifier) 检查TestIdentifier 的父级的TestSource。如果是ClassSource,您可以通过classSource.getJavaClass() 访问Class

【讨论】:

  • 建议的决定并不适用于所有情况,尽管其中一些情况可以涵盖。例如,它不适用于 JUnit5 动态测试 - 如果正在运行动态测试 testPlan.getParent(identifier).get().getSource() 不包含 ClassSource 在运行 Junit4 参数化测试时 testPlan.getParent(identifier)。该参数化测试的 get().getSource() 为空。
【解决方案2】:

我找到了描述情况的临时解决方案。 这个想法是遍历所有父母并首先找到包含 ClassSources,然后使用该 ClassSource。

private static String findTestMethodClassName(TestPlan testPlan, TestIdentifier identifier) {
    identifier.getSource().orElseThrow(IllegalStateException::new);
    identifier.getSource().ifPresent(source -> {
        if (!(source instanceof MethodSource)) {
            throw new IllegalStateException("identifier must contain MethodSource");
        }
    });


    TestIdentifier current = identifier;
    while (current != null) {
        if (current.getSource().isPresent() && current.getSource().get() instanceof ClassSource) {
            return ((ClassSource) current.getSource().get()).getClassName();
        }
        current = testPlan.getParent(current).orElse(null);
    }
    throw new IllegalStateException("Class name not found");
}

尽管该解决方案满足了我的需求,但它不能保证框架行为将来不会改变,并且目前不能被认为是可靠的。

问题已发布到https://github.com/junit-team/junit5/issues/737

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-04
    • 1970-01-01
    相关资源
    最近更新 更多