使用 JUnit 5,如何在测试实例之间共享 `ExtensionContext.Store` 中的信息?
With JUnit 5, how to share information in `ExtensionContext.Store` between test instances?
我运行遇到 JUnit 5(5.0 或 5.1)和自定义扩展的问题。
我们正在使用服务加载器加载所有实现,然后修改我们的扩展程序的引导方式。这些实现只能加载一次,所以我考虑使用 ExtensionContext.Store
并将其放在那里。每个后续测试实例都会从 Store
而不是通过服务加载器加载它。
现在,我什至知道层次上下文结构,我知道有一些 "root" 上下文可以通过 ExtensionContext.getRoot()
获得。但是这个 "root" 上下文(JupiterEngineExtensionContext
的实例)并不是真正的根 - 每个测试实例 .
都有不同的上下文
假设您有 FooTest
和 BarTest
,然后为每个打印出 getRoot()
产量:
org.junit.jupiter.engine.descriptor.JupiterEngineExtensionContext@1f9e9475
org.junit.jupiter.engine.descriptor.JupiterEngineExtensionContext@6c3708b3
因此尝试从 Store
中检索以前存储的信息失败。
- 有这个限制是有意的吗?它使
ClassExtensionContext
和 JupiterEngineExtensionContext
之间的界限变得非常模糊。
- 是否有另一种方法可以通过扩展程序全局存储一些信息?
这是我尝试与商店合作的(非常)简化的版本(基本上删除了所有其他信息)。我还添加了一些 System.out.print()
调用来强调我所看到的内容。在两个 测试 类 上执行此扩展会产生我上面描述的结果:
public class MyExtension implements BeforeAllCallback {
@Override
public void beforeAll(ExtensionContext context) throws Exception {
System.out.println(context.getRoot());
if (context.getRoot().getStore(Namespace.create(MyExtension.class)).get("someIdentifier", String.class) == null) {
context.getRoot().getStore(Namespace.create(MyExtension.class)).put("someIdentifier", "SomeFooString");
} else {
// this is never executed
System.out.println("Found it, no need to store anything again!");
}
}
}
编辑:这是 GH(link) 上的一个最小项目,运行 by mvn clean install
,它显示了我看到的行为。
我只是逐字复制了您的 MyExtension
(即零改动)和 运行 FooTest
和 BarTest
。
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
@ExtendWith(MyExtension.class)
class FooTest {
@Test
void test() {
}
}
和
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
@ExtendWith(MyExtension.class)
class BarTest {
@Test
void test() {
}
}
结果是:
org.junit.jupiter.engine.descriptor.JupiterEngineExtensionContext@2280cdac
org.junit.jupiter.engine.descriptor.JupiterEngineExtensionContext@2280cdac
Found it, no need to store anything again!
因此,getRoot()
按照记录工作。
为什么您看到两个不同的根的唯一解释是您必须在不同的进程中执行测试。
请记住根 ExtensionContext
实例绑定到您的测试套件的当前执行。
所以如果你 运行 FooTest
和 BarTest
在一个 IDE 中一个接一个地出现,那实际上会导致两个 "test suites" 具有不同的根.如果将构建工具配置为 fork between test classes.
也是如此
然而,如果您在单个 "test suite" 中同时执行两个测试 class(例如,通过告诉您的 IDE 到 运行 同一包中的所有测试或相同的源代码树)然后你会看到有一个根,就像我上面提供的输出一样。
但是请注意,在 1.0.3 版之前的 junit-platform-surefire-provider
存在一个问题,即提供商为每个测试 class 启动了 JUnit 平台。这会产生 forking 的外观运行ce,即使 Surefire 实际上并未启动新的 JVM 进程。有关详细信息,请参阅 https://github.com/junit-team/junit5/pull/1137。
我运行遇到 JUnit 5(5.0 或 5.1)和自定义扩展的问题。
我们正在使用服务加载器加载所有实现,然后修改我们的扩展程序的引导方式。这些实现只能加载一次,所以我考虑使用 ExtensionContext.Store
并将其放在那里。每个后续测试实例都会从 Store
而不是通过服务加载器加载它。
现在,我什至知道层次上下文结构,我知道有一些 "root" 上下文可以通过 ExtensionContext.getRoot()
获得。但是这个 "root" 上下文(JupiterEngineExtensionContext
的实例)并不是真正的根 - 每个测试实例 .
假设您有 FooTest
和 BarTest
,然后为每个打印出 getRoot()
产量:
org.junit.jupiter.engine.descriptor.JupiterEngineExtensionContext@1f9e9475
org.junit.jupiter.engine.descriptor.JupiterEngineExtensionContext@6c3708b3
因此尝试从 Store
中检索以前存储的信息失败。
- 有这个限制是有意的吗?它使
ClassExtensionContext
和JupiterEngineExtensionContext
之间的界限变得非常模糊。 - 是否有另一种方法可以通过扩展程序全局存储一些信息?
这是我尝试与商店合作的(非常)简化的版本(基本上删除了所有其他信息)。我还添加了一些 System.out.print()
调用来强调我所看到的内容。在两个 测试 类 上执行此扩展会产生我上面描述的结果:
public class MyExtension implements BeforeAllCallback {
@Override
public void beforeAll(ExtensionContext context) throws Exception {
System.out.println(context.getRoot());
if (context.getRoot().getStore(Namespace.create(MyExtension.class)).get("someIdentifier", String.class) == null) {
context.getRoot().getStore(Namespace.create(MyExtension.class)).put("someIdentifier", "SomeFooString");
} else {
// this is never executed
System.out.println("Found it, no need to store anything again!");
}
}
}
编辑:这是 GH(link) 上的一个最小项目,运行 by mvn clean install
,它显示了我看到的行为。
我只是逐字复制了您的 MyExtension
(即零改动)和 运行 FooTest
和 BarTest
。
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
@ExtendWith(MyExtension.class)
class FooTest {
@Test
void test() {
}
}
和
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
@ExtendWith(MyExtension.class)
class BarTest {
@Test
void test() {
}
}
结果是:
org.junit.jupiter.engine.descriptor.JupiterEngineExtensionContext@2280cdac
org.junit.jupiter.engine.descriptor.JupiterEngineExtensionContext@2280cdac
Found it, no need to store anything again!
因此,getRoot()
按照记录工作。
为什么您看到两个不同的根的唯一解释是您必须在不同的进程中执行测试。
请记住根 ExtensionContext
实例绑定到您的测试套件的当前执行。
所以如果你 运行 FooTest
和 BarTest
在一个 IDE 中一个接一个地出现,那实际上会导致两个 "test suites" 具有不同的根.如果将构建工具配置为 fork between test classes.
然而,如果您在单个 "test suite" 中同时执行两个测试 class(例如,通过告诉您的 IDE 到 运行 同一包中的所有测试或相同的源代码树)然后你会看到有一个根,就像我上面提供的输出一样。
但是请注意,在 1.0.3 版之前的 junit-platform-surefire-provider
存在一个问题,即提供商为每个测试 class 启动了 JUnit 平台。这会产生 forking 的外观运行ce,即使 Surefire 实际上并未启动新的 JVM 进程。有关详细信息,请参阅 https://github.com/junit-team/junit5/pull/1137。