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
}
}
private static boolean started = false;
static{
if (!started) {
started = true;
try {
setUpDriver(); //method where you initialize your driver
} catch (MalformedURLException e) {
}
}
}
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;
}
使用方法:
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 { ... }
}
6条答案
按热度按时间eimct9ow1#
在junit5中,现在可以通过创建一个自定义扩展来实现这一点,从中可以在根测试上下文上注册一个shutdown钩子。
你的分机是这样的;
然后,需要至少执行一次的任何测试类都可以使用以下注解:
当您在多个类上使用此扩展时,启动和关闭逻辑将只被调用一次。
js5cn81o2#
以上建议不适用于我,所以我这样解决了这个问题:
向基本抽象类(我是指在setupdriver()方法中初始化驱动程序的抽象类)添加以下代码部分:
现在,如果您的测试类将从基抽象类扩展->setupdriver()方法将在第一次@test之前执行,每次项目运行只执行一次。
soat7uwm3#
我不知道有什么办法做那件事。
我只想确保@beforeall的所有代码都调用某个单例来使init工作(可能是以一种懒惰的方式来避免重复)。
可能不方便。。。我看到的另一个选择是:我假设您的测试在特定的jvm作业中运行。您可以将一个代理挂接到jvm运行中,这样init就可以为您工作。
除此之外:这两个建议在某种程度上听起来像是一个黑客。在我看来,真正的答案是:后退一步,仔细检查您的环境对它的依赖关系。然后找到一种方法来准备您的环境,这样您的测试就会出现并且“正确的事情”会自动发生。换句话说:考虑一下为您带来这个问题的体系结构。
vxqlmq5t4#
以下是我对@phillip gayret非常好的回答的poc改进,跟随@mihnea giurgea的脚步。
我的子问题:如何访问共享的单例资源(也许你也在想……)
侧边栏:在我的实验中,我发现使用多个
@ExtendWith(...)
似乎窝得很好。即便如此,我记得在我摸索的某个时候,它并不是这样工作的,所以你应该确保你的用例是正确工作的[sic]。因为您可能很着急,所以沙漠是第一位的:下面是运行“文件夹中的所有测试”的输出:
当然,只要运行一个测试类就可以得到:
还有一个具体的测试,现在可以预料到:
还跟我在一起吗?然后你可能会喜欢看到实际的代码。。。
哈哈-我的小笑话。。。这些东西实际上是代码:base64编码的zip创建为:
尽管如此,您还是应该怀疑正在展开该数据块。它可能是一个有点硬币钱包偷或os砖。谁知道呢(我应该把这些都推到一个github上,但我太懒了。无论如何……)
真正的快乐(tm):
lf5gs5x25#
根据@philipp的建议,这里有一个更完整的代码片段:
使用方法:
测试执行顺序为:
…无论您选择运行单个@test(例如testone.testone),还是整个测试类(testone),或多个/所有测试,这都是正确的。
ars1skjm6#
您可以用一个定义
static
BeforeAll
(这样它就不能被覆盖)。例如。:对于每个实现类,这个方法将被调用一次,因此您需要定义一种方法来初始化连接一次,然后对其他调用不做任何操作。