该@BeforeAll注释标记在所有测试之前运行的方法类.
http://junit.org/junit5/docs/current/user-guide/#writing-tests-annotations
但是在所有类中,有没有办法在所有测试之前运行一些代码?
我想确保测试使用一组特定的数据库连接,并且在运行任何测试之前必须进行这些连接的全局一次性设置.
Phi*_*ret 31
现在可以通过创建自定义扩展在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
}
}
Run Code Online (Sandbox Code Playgroud)
然后,您需要执行至少一次的任何测试类都可以使用以下注释进行注释:
@ExtendWith({YourExtension.class})
Run Code Online (Sandbox Code Playgroud)
在多个类上使用此扩展时,启动和关闭逻辑将仅调用一次.
LeO*_*LeO 10
@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 {
private static boolean started = false;
// Gate keeper to prevent multiple Threads within the same routine
final static Lock lock = new ReentrantLock();
@Override
public void beforeAll(final ExtensionContext context) throws Exception {
// lock the access so only one Thread has access to it
lock.lock();
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
}
// free the access
lock.unlock();
}
@Override
public void close() {
// Your "after all tests" logic goes here
}
}
Run Code Online (Sandbox Code Playgroud)
如下所述,JUnit5 提供了一个自动扩展注册。为此,在src/test/resources/名为 的目录中/META-INF/services添加 并添加名为 的文件org.junit.jupiter.api.extension.Extension。将您班级的完全分类名称添加到此文件中,例如
at.myPackage.BeforeAllTestsExtension
Run Code Online (Sandbox Code Playgroud)
接下来在同一个 Junit 配置文件中启用
junit.jupiter.extensions.autodetection.enabled=true
Run Code Online (Sandbox Code Playgroud)
有了这个扩展程序会自动附加到您的所有测试中。
您可以使用定义 a 的接口标记使用您的数据库的每个测试类static BeforeAll(以便它不能被覆盖)。例如:
interface UsesDatabase {
@BeforeAll
static void initializeDatabaseConnections() {
// initialize database connections
}
}
Run Code Online (Sandbox Code Playgroud)
此方法将为每个实现类调用一次,因此您需要定义一种方法来初始化您的连接一次,然后对其他调用不做任何事情。
小智 5
根据@Philipp 的建议,这里有一个更完整的代码片段:
import static org.junit.jupiter.api.extension.ExtensionContext.Namespace.GLOBAL;
import org.junit.jupiter.api.extension.BeforeAllCallback;
import org.junit.jupiter.api.extension.ExtensionContext;
public abstract class BaseSetupExtension
implements BeforeAllCallback, ExtensionContext.Store.CloseableResource {
@Override
public void beforeAll(ExtensionContext context) throws Exception {
// We need to use a unique key here, across all usages of this particular extension.
String uniqueKey = this.getClass().getName();
Object value = context.getRoot().getStore(GLOBAL).get(uniqueKey);
if (value == null) {
// First test container invocation.
context.getRoot().getStore(GLOBAL).put(uniqueKey, this);
setup();
}
}
// Callback that is invoked <em>exactly once</em>
// before the start of <em>all</em> test containers.
abstract void setup();
// Callback that is invoked <em>exactly once</em>
// after the end of <em>all</em> test containers.
// Inherited from {@code CloseableResource}
public abstract void close() throws Throwable;
}
Run Code Online (Sandbox Code Playgroud)
如何使用:
public class DemoSetupExtension extends BaseSetupExtension {
@Override
void setup() {}
@Override
public void close() throws Throwable {}
}
@ExtendWith(DemoSetupExtension.class)
public class TestOne {
@BeforeAll
public void beforeAllTestOne { ... }
@Test
public void testOne { ... }
}
@ExtendWith(DemoSetupExtension.class)
public class TestTwo {
@BeforeAll
public void beforeAllTestTwo { ... }
@Test
public void testTwo { ... }
}
Run Code Online (Sandbox Code Playgroud)
测试执行顺序为:
DemoSetupExtension.setup (*)
TestOne.beforeAllTestOne
TestOne.testOne
TestOne.afterAllTestOne
TestTwo.beforeAllTestTwo
TestTwo.testTwo
TestTwo.afterAllTestTwo
DemoSetupExtension.close (*)
Run Code Online (Sandbox Code Playgroud)
...无论您选择运行单个@Test(例如TestOne.testOne),还是整个测试类(TestOne),或多个/所有测试,这都是正确的。
| 归档时间: |
|
| 查看次数: |
16282 次 |
| 最近记录: |