在 JUnit 5 中,如何在所有测试之前运行代码
该批注将方法标记为在类中的所有测试之前运行。@BeforeAll
http://junit.org/junit5/docs/current/user-guide/#writing-tests-annotations
但是,有没有办法在所有类中的所有测试之前运行一些代码?
我想确保测试使用一组特定的数据库连接,并且在运行任何测试之前必须对这些连接进行全局一次性设置。
该批注将方法标记为在类中的所有测试之前运行。@BeforeAll
http://junit.org/junit5/docs/current/user-guide/#writing-tests-annotations
但是,有没有办法在所有类中的所有测试之前运行一些代码?
我想确保测试使用一组特定的数据库连接,并且在运行任何测试之前必须对这些连接进行全局一次性设置。
现在,通过创建自定义扩展,可以在 JUnit5 中实现这一点,从中可以在根测试上下文中注册关闭挂钩。
您的扩展将如下所示;
import org.junit.jupiter.api.extension.BeforeAllCallback;
import org.junit.jupiter.api.extension.ExtensionContext;
import static org.junit.jupiter.api.extension.ExtensionContext.Namespace.GLOBAL;
public class YourExtension implements BeforeAllCallback, ExtensionContext.Store.CloseableResource {
private static boolean started = false;
@Override
public void beforeAll(ExtensionContext context) {
if (!started) {
started = true;
// Your "before all tests" startup logic goes here
// The following line registers a callback hook when the root test context is shut down
context.getRoot().getStore(GLOBAL).put("any unique name", this);
}
}
@Override
public void close() {
// Your "after all tests" logic goes here
}
}
然后,任何需要至少执行一次的测试类都可以使用以下内容进行注释:
@ExtendWith({YourExtension.class})
在多个类上使用此扩展时,启动和关闭逻辑将仅调用一次。
来自@Philipp Gayret已经提供的答案在并行测试JUnit时存在一些问题(即)。junit.jupiter.execution.parallel.enabled = true
因此,我将解决方案调整为:
import static org.junit.jupiter.api.extension.ExtensionContext.Namespace.GLOBAL;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import org.junit.jupiter.api.extension.BeforeAllCallback;
import org.junit.jupiter.api.extension.ExtensionContext;
public class BeforeAllTestsExtension extends BasicTestClass
implements BeforeAllCallback, ExtensionContext.Store.CloseableResource {
/** Gate keeper to prevent multiple Threads within the same routine */
private static final Lock LOCK = new ReentrantLock();
/** volatile boolean to tell other threads, when unblocked, whether they should try attempt start-up. Alternatively, could use AtomicBoolean. */
private static volatile boolean started = false;
@Override
public void beforeAll(final ExtensionContext context) throws Exception {
// lock the access so only one Thread has access to it
LOCK.lock();
try {
if (!started) {
started = true;
// Your "before all tests" startup logic goes here
// The following line registers a callback hook when the root test context is
// shut down
context.getRoot().getStore(GLOBAL).put("any unique name", this);
// do your work - which might take some time -
// or just uses more time than the simple check of a boolean
}
finally {
// free the access
LOCK.unlock();
}
}
@Override
public void close() {
// Your "after all tests" logic goes here
}
}
如下所述,JUnit5 提供了自动扩展注册。为此,请在名为 的目录中添加一个,并添加一个名为 的文件。将类的完全分类名称添加到此文件中,例如src/test/resources/
/META-INF/services
org.junit.jupiter.api.extension.Extension
at.myPackage.BeforeAllTestsExtension
接下来在同一 Junit 配置文件中启用
junit.jupiter.extensions.autodetection.enabled=true
这样,扩展将自动附加到所有测试中。