You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spock全局setup中使用Stub/Mock及@Shared对象注入问题咨询

解决Spock中@Shared Facade无法注入子类Mock EventBus的问题

这个问题的核心在于**@Shared字段的初始化时机**:Spock中@Shared修饰的字段会在测试类加载阶段就完成初始化,远早于子类中Mock实例的创建,也早于setupSpec方法的执行。你原来的父类直接在字段声明时初始化facade,此时子类重写的eventBus()方法返回的要么是未初始化的Mock,要么还是父类的默认实现,自然无法正确注入。

下面是两种可行的解决方案,优先推荐第一种,更符合你的复用需求:

方案一:调整Facade的初始化时机到setupSpec方法

把Facade的初始化从字段声明移到setupSpec中,这样就能保证在子类的Mock创建完成后,再调用子类重写的eventBus()方法来注入依赖:

抽象父类AbstractSpec

abstract class AbstractSpec extends Specification {
  @Shared Facade facade

  def setupSpec() {
    // 这里才初始化Facade,此时子类的eventBus()已经能返回正确的Mock/Stub
    facade = new Facade(eventBus())
    // 执行Facade的统一初始化逻辑,比如调用初始化方法
    // facade.init()
  }

  // 默认提供一个空实现的EventBus Stub
  EventBus eventBus() {
    // Groovy闭包直接实现接口,空处理push方法
    { event -> } as EventBus
  }
}

需要验证EventBus的子类DerivedSpec

class DerivedSpec extends AbstractSpec {
  // 必须用@Shared,因为setupSpec是类级别的钩子,非@Shared字段此时还未实例化
  @Shared EventBus eventBus = Mock()

  // 重写父类方法,返回我们的Mock
  @Override
  EventBus eventBus() {
    return eventBus
  }

  def "check if proper event was emitted"() {
    when:
    def someId = facade.doSomething().block()

    then:
    // 直接验证Mock的调用和参数
    1 * eventBus.push(_ as ExpectedEvent) >> { ExpectedEvent event ->
      assert event.id == someId
    }
  }
}

原理说明

  • setupSpec是Spock的类级别初始化钩子,会在当前测试类的所有测试方法执行前仅执行一次,且此时子类的@Shared字段已经完成初始化。
  • 父类在setupSpec中调用eventBus()时,会优先使用子类重写的实现,从而将Mock正确注入到Facade中。
  • 普通测试类直接继承AbstractSpec即可使用默认的空实现EventBus,无需额外修改。

方案二:使用Spock扩展实现依赖注入(进阶)

如果你的测试场景更复杂,比如需要大量不同的依赖替换,可以自定义Spock扩展来实现类似依赖注入的功能。不过对于当前场景来说,方案一已经足够简洁高效,这里只做简单说明:

你可以实现IGlobalExtension或ISpecificationExtension,在Spec初始化阶段动态替换EventBus的实现。不过这种方式需要编写额外的扩展代码,适合大规模测试套件的统一管理。

避免的坑

  • 不要在@Shared字段声明时直接初始化依赖注入的对象,否则会错过子类的重写逻辑。
  • 子类中用于替换的Mock/Stub必须用@Shared修饰,否则在setupSpec执行时还未创建。

内容的提问来源于stack exchange,提问作者Maciekkk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 23:37:38