当前位置: 首页 > 面试题库 >

如何在多个测试类之间共享JUnit BeforeClass逻辑

吕和风
2023-03-14
问题内容

当前,我所有的JUnit测试都从一个通用的基类扩展而来,该基类提供了带有@BeforeClass和标记的方法
@AfterClass-真正要做的就是设置一堆静态资源/服务以供测试使用。

由于某些原因,这对我来说似乎很尴尬:

  1. 根据我的理解,JUnit4的部分要点是我们不再需要这种经典的测试继承。
  2. 当我将这些测试作为套件的一部分而不是单独运行(我们经常这样做)时,多次调用@BeforeClass@AfterClass,从而减慢了测试的速度-我们实际上应该只调用一次

我想做的是以某种方式将当前的BeforeClass / AfterClass逻辑移出继承链,并移到可以由单个测试和整个套件共享的东西中。

能做到吗? 如果是这样,怎么办? (如果有关系,我正在使用JUnit 4.7,将其更新为其他版本可能会很困难)


问题答案:

第一个问题的解决方案是org.junit.rules.ExternalResource通过@ClassRuleJUnit
4.9中引入的,将逻辑移到与测试挂钩的扩展中:

public class MyTest {
    @ClassRule
    public static final TestResources res = new TestResources();
    @Test
    public void testFoo() {
        // test logic here
    }
}

public class TestResources extends ExternalResource {
    protected void before() {
        // Setup logic that used to be in @BeforeClass
    }
    protected void after() {
        // Setup logic that used to be in @AfterClass
    }
}

这样,以前由基类管理的资源将移出测试类层次结构,并移入更多的模块化/可使用的“资源”,这些资源可以在类运行之前创建,而在类运行之后销毁。

至于同时解决两个问题-即:作为单个测试的一部分和作为套件的一部分,具有相同的高级设置/拆卸运行-似乎对此没有任何特定的内置支持。 。 但是…
您可以自己实现

只需将@ClassRule资源创建更改为工厂模式,该模式会在内部进行引用计数,以确定是否创建/销毁资源。

例如(请注意,这很粗糙,可能需要一些调整/错误处理才能确保其健壮性):

public class TestResources extends ExternalResource {
    private static int refCount = 0;

    private static TestResources currentInstance;

    public static TestResources getTestResources () {
        if (refCount == 0) {
            // currentInstance either hasn't been created yet, or after was called on it - create a new one
            currentInstance = new TestResources();
        }
        return currentInstance;
    }

    private TestResources() {
        System.out.println("TestResources construction");
        // setup any instance vars
    }

    protected void before() {
        System.out.println("TestResources before");
        try {
            if (refCount == 0) {
                System.out.println("Do actual TestResources init");
            }
        }
        finally {
            refCount++;
        }
    }

    protected void after() {
        System.out.println("TestResources after");
        refCount--;
        if (refCount == 0) {
            System.out.println("Do actual TestResources destroy");
        }
    }
}

您的套件/测试类都将@ClassResource通过工厂方法使用资源:

@RunWith(Suite.class)
@SuiteClasses({FooTest.class, BarTest.class})
public class MySuite {
    @ClassRule
    public static TestResources res = TestResources.getTestResources();
    @BeforeClass
    public static void suiteSetup() {
        System.out.println("Suite setup");
    }
    @AfterClass
    public static void suiteTeardown() {
        System.out.println("Suite teardown");
    }
}
public class FooTest {
    @ClassRule
    public static TestResources res = TestResources.getTestResources();

    @Test
    public void testFoo() {
        System.out.println("testFoo");
    }
}
public class BarTest {
    @ClassRule
    public static TestResources res = TestResources.getTestResources();

    @Test
    public void testBar() {
        System.out.println("testBar");
    }
}

在运行单个测试时,重新引用不会有任何效果-“实际初始化”和“实际拆卸”将只发生一次。在套件中运行时,套件将创建TestResource,而各个测试将仅重用已实例化的TestResource(引用计数使它不会在套件中的测试之间被实际破坏和重新创建)。



 类似资料:
  • 我正在努力理解使用的好处。文档和其他帖子(Junit@Rule是如何工作的?)所有这些都暗指能够在类内的测试之间共享代码和/或在测试类之间共享代码。 在功能/集成测试中,我试图使用进行DB连接,但我不知道如何跨类共享该连接。事实上,在这种情况下,我并没有看到比有什么好处。我是不是用错了,还是我遗漏了什么?

  • 我有一个测试类的testng套件,我正在通过一个testng.xml文件运行它。这个很管用。所有测试都是串行运行的,因此没有并行执行障碍。 当然,通过类成员变量在单个类中的测试方法之间共享状态是很容易的,但是我不知道如何在测试类之间共享状态。

  • 问题内容: 我们遇到了适用于多线程的方案。 在主线程中,执行一些逻辑操作并更新数据库,在某种程度上,它将调用另一个服务来更新数据库,该服务在另一个线程中运行。 我们希望两个线程共享同一个事务,这意味着任何一个线程中的任何一个操作都将失败,那么另一个线程中的该操作也将被回滚。 但是工作了几天,我发现一些帖子说JTA不支持多线程。当前我们使用Bitronix作为JTA提供者,有没有人知道Bitroni

  • 我们有两个网站有多种产品。我们决定在这些网站之间只共享一个目录,其中包含所有产品,没有任何重复。 到目前为止,我可以在两个网站上看到所有的产品,但是我们有一些产品应该只在一个网站上显示。 有什么解决办法吗?我们使用的是Hybris 5.2 到目前为止,我们的想法是: 使用类别组织(站点A的类别,站点B的类别,共享产品的类别 在我们的情况下,哪种解决方案是最好的,还有其他解决方案吗?

  • 问题内容: 一个程序,该程序创建在可连接队列上工作的多个进程,并且最终可能会操纵全局字典来存储结果。(因此,每个子进程都可以用来存储其结果,并查看其他子进程正在产生什么结果) 如果我在子进程中打印字典,则可以看到对它进行的修改(即在上)。但是在主流程加入之后,如果我打印D,那就是空洞的字典! 我了解这是同步/锁定问题。有人可以告诉我这里发生了什么,如何同步对的访问? 问题答案: 普遍的答案涉及使用

  • 问题内容: 我想知道是否有某种方式可以在两个或多个Servlet之间共享变量或对象,我的意思是某种“标准”方式。我认为这不是一个好习惯,但是是构建原型的更简单方法。 我不知道这是否取决于所使用的技术,但我将使用Tomcat 5.5 我想共享一个简单类的对象的Vector(仅公共属性,字符串,int等)。我的意图是在数据库中拥有一个静态数据,当Tomcat停止时,它显然会丢失。(仅用于测试) 问题答