【问题标题】:What is wrong with my Spec?我的规格有什么问题?
【发布时间】:2025-12-19 23:00:12
【问题描述】:

所以,我在下面有这个非常简单的规范。我有一个不是控制器或服务或类似的类。这是一个工作类。它依赖于两个服务:updateService 和 directoryTypeService。它运行 Redis 异步作业,位于 /grails-app/jobs 文件夹下。

我只想确保每当我调用此 job#perform() 方法(返回类型为 void)时,调用一个名为 UpdateService#completeClaiming 的给定依赖方法,但不会调用 UpdateService#requestNewPin。 (顺便说一下,Listing 是一个领域类)。

当我运行此规范时,我不断收到一条错误消息:“此时不再需要调用 'completeClaiming'。请求结束。”

我在这里做错了什么?有什么疯狂的猜测吗?

@Mock(Listing)
class SubmissionJobSpec extends Specification {

def directoryTypeServiceMock
def updateServiceMock
def job

def setup(){
    job = new SubmissionJob()
    directoryTypeServiceMock = mockFor(DirectoryTypeService)
    updateServiceMock = mockFor(UpdateService)

    job.updateService = updateServiceMock.createMock()
    job.directoryTypeService = directoryTypeServiceMock.createMock()
}


def "if the directory is enabled and the pin status is ENTERED, we should call updateService.completeClaiming"() {
    given:
    directoryTypeServiceMock.demand.isUpdateEnabled { DirectoryType d, Country c -> return true}

    new Listing(
            location: new Location(country: Country.DE)
    ).save(failOnError: true, validate: false)

    when:
    job.perform(Listing.last().id, true)

    then:
    1 * updateServiceMock.completeClaiming(Listing.last(), true) >> new ListingEvent(output: [success: true])
    0 * updateServiceMock.requestNewPin(_ as Listing, true)
}

【问题讨论】:

    标签: grails spock


    【解决方案1】:

    您似乎混淆了 Groovy 和 Spock 模拟。对于使用 mockFor() 创建的 Groovy 模拟,您不能使用 Spock 模拟语法(例如 0 * updateServiceMock.requestNewPin(_ as Listing, true))。 Spock 模拟是使用Mock()Stub()Spy() 创建的。我不知道有什么好的理由在 Spock 规范中使用 Groovy 模拟。

    【讨论】:

    • 谢谢,彼得。你是对的,我对两者都感到困惑。但是,有没有办法使用 Grails 模拟来检查协作者方法执行了多少次,例如 0 * updateServiceMock.requestNewPin(_ as Listing, true) 的示例?
    • @felipecao Spock 的主要功能之一是交互测试。这是首先使用该库的主要原因。改用 Spock 模拟,您将能够测试您的交互。 Grails 模拟本身不支持它。