【问题标题】:Spock extension's start method invoked multiple timesSpock 扩展的 start 方法被多次调用
【发布时间】:2017-05-15 14:40:28
【问题描述】:

我有一堆基于 Spock 和 Geb 的功能测试。我想在执行这些测试之前和之后执行一些操作。因此,我创建了全局扩展并为该扩展的 start() 和 stop() 方法添加了所需的功能。但问题是,尽管 Spock 文档 (http://spockframework.org/spock/docs/1.1/all_in_one.html#_global_extensions) 指出,在每个 Spock 规范之前/之后都会调用 start/stop 方法:

start() 在 Spock 执行开始时调用一次

stop() 在 Spock 执行结束时调用一次

我做错了什么还是 Spock 文档对这些方法的行为不正确?

【问题讨论】:

  • 您能否提供更多有关您如何运行测试的信息。 (Maven/Gradle/...)
  • 我使用“mvn clean test”命令运行测试。我想在每个规范之前/之后调用启动/停止方法是设计使然,因为我使用 Spock 报告库,该库也被实现为全局扩展并且它的工作方式相同。但也许还有其他方法可以实现我所需要的,即在开始所有测试规范之前和完成它们之后调用一些操作?

标签: testing spock geb


【解决方案1】:

@MantasG Spock 实现了一个 JUnit Runner 并且不控制它的执行方式。全局扩展在RunContext 中管理,该ThreadLocal 保存在ThreadLocal 中。如果 surefire 使用多个线程来执行测试,那么这将创建多个 RunContext 实例,每个实例都有自己的全局扩展列表。如果您使用的是EmbeddedSpecRunner,那么这也会创建一个新的隔离上下文。

此上下文将一直存在,直到线程终止。这将是 测试运行完成后更准确地删除上下文, 但是 JUnit Runner SPI 没有提供足够的钩子。那 说,由于大多数环境为每次测试运行派生一个新的 JVM,这 在实践中应该不是什么大问题。

根据你想要做什么,还有其他方法:

  1. 您可以使用JUnitRunListenertestRunStarted/testRunFinished 挂钩。请注意,您需要通过surefire 进行注册。
  2. 如果您真的只想运行一次,那么您可以使用故障安全而不是万无一失,并使用集成前和集成后目标。
  3. 您可以对每个start/stop 调用使用静态字段和计数器来破解某些内容,如果计数器为 0,则执行您的开始操作,并在计数器达到 0 时执行您的停止操作。当然,您将需要确保此线程安全。

请注意,surefire 还支持forking multiple JVMs,这也会影响选项 1 和 3。

【讨论】:

  • 谢谢伦纳德,你的回答很全面。所有建议的选项都可以用来实现我所需要的,但就我而言,这些都不起作用,因为我的 Surefire 配置中有“false”。在我切换到“reuseForks=true”之后,一切都开始工作了。现在我什至可以使用 Spock 扩展来实现我所需要的。
【解决方案2】:

我相信在您的测试套件中的每个测试规范开始时都会调用 Spock,因此每次执行都会运行启动和停止

我认为您可能想查看在问题中链接的同一文档中找到的夹具方法: http://spockframework.org/spock/docs/1.1/all_in_one.html#_specification

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-02
    相关资源
    最近更新 更多