Java 在 JUnit 5 中,如何在所有测试之前运行代码

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/43282798/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 00:50:43  来源:igfitidea点击:

In JUnit 5, how to run code before all tests

javajunitjunit5

提问by Rob N

The @BeforeAllannotation marks a method to run before all tests in a class.

@BeforeAll注释标记的方法来在所有测试之前运行的类

http://junit.org/junit5/docs/current/user-guide/#writing-tests-annotations

http://junit.org/junit5/docs/current/user-guide/#writing-tests-annotations

But is there a way to run some code before alltests, in all classes?

但是有没有办法在所有测试之前在所有类中运行一些代码?

I want to ensure that tests use a certain set of database connections, and the global one-time setup of these connections must occur beforerunning anytests.

我想确保测试使用一组特定的数据库连接,并且必须运行任何测试之前对这些连接进行全局一次性设置。

回答by GhostCat

I am not aware of a mean to do that.

我不知道这样做的方法。

I would simply make sure that all code for @BeforeAll calls a certain singleton to make that init work (probably in a lazy way to avoid repetition).

我会简单地确保@BeforeAll 的所有代码都调用某个单例来使该 init 工作(可能以一种懒惰的方式避免重复)。

Probably not convenient ... the only other option I see: I assume your tests run within a specific JVM job. You couldhook an agentinto that JVM run, that does that init work for you.

可能不方便……我看到的唯一其他选择:我假设您的测试在特定的 JVM 作业中运行。您可以代理挂接到该 JVM 运行中,这样 init 就可以为您工作。

Beyond that: both suggestions sounds somehow like a hack to me. The realanswer in my eyes: step back, and carefully examine your environment on its dependencies. And then find a way to prepareyour environment in a way that your tests come up and the "right thing" happens automatically. In other words: consider looking into the architecture that bought you this problem.

除此之外:这两个建议对我来说听起来有点像黑客。我眼中的真正答案是:退后一步,仔细检查您的环境的依赖关系。然后找到一种方法来准备您的环境,使您的测试出现并且“正确的事情”自动发生。换句话说:考虑研究给你带来这个问题的架构。

回答by mfulton26

You can mark each of your test classes that uses your database with an interface that defines a staticBeforeAll(so that it cannot be overridden). e.g.:

您可以使用定义 a 的接口标记使用您的数据库的每个测试类staticBeforeAll(以便它不能被覆盖)。例如:

interface UsesDatabase {
    @BeforeAll
    static void initializeDatabaseConnections() {
        // initialize database connections
    }
}

This method will be invoked once for each implementing class so you will need to define a way to initialize your connections only once and then do nothing for the other calls.

此方法将为每个实现类调用一次,因此您需要定义一种方法来初始化您的连接一次,然后对其他调用不做任何事情。

回答by Philipp Gayret

This is now possible in JUnit5 by creating a custom Extension, from which you can register a shutdown hook on the root test-context.

这现在可以通过创建自定义扩展在 JUnit5 中实现,您可以从中注册一个在根测试上下文上的关闭挂钩。

Your extension would look like this;

你的扩展看起来像这样;

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
    }
}

Then, any tests classes where you need this executed at least once, can be annotated with:

然后,您需要至少执行一次的任何测试类都可以注释为:

@ExtendWith({YourExtension.class})

When you use this extension on multiple classes, the startup and shutdown logic will only be invoked once.

当你在多个类上使用这个扩展时,启动和关闭逻辑只会被调用一次。

回答by Sergii

Above advises do notwork for me, so I solved this problem like this:

以上建议做不是为我工作,所以我解决了这个问题是这样的:

Add to your Base abstract class (I mean abstract class where you initialize your driver in setUpDriver()method) this part of code:

将这部分代码添加到您的 Base 抽象类(我的意思是您在setUpDriver()方法中初始化驱动程序的抽象类)中:

private static boolean started = false;
static{
    if (!started) {
        started = true;
        try {
            setUpDriver();  //method where you initialize your driver
        } catch (MalformedURLException e) {
        }
    }
}

And now, if your test classes will extendsfrom Base abstract class -> setUpDriver()method will be executed before first @Test only ONEtime per project run.

现在,如果你的测试类将扩展从基本抽象类- > setUpDriver()方法将被执行之前,首先@Test只ONE每个项目的运行时间。