【问题标题】:spock reusable closure in mocks模拟中的spock可重用闭包
【发布时间】:2015-11-02 08:22:34
【问题描述】:

如何在 spock 模拟中重用闭包?

我可以在运行时键入闭包(mock.sth({closure}),但我如何创建命名的 clsoure 以供重用或提高代码可读性(mock.sth(hasStuffAsExpected))?

我有课:

class Link {
  String url
  boolean openInNewWindow
}

现在有服务了

interface LinkService {
  boolean checkStuff(Link link)
}

在我的测试中,我想创建这样的东西:

@Shared def linkIsOpenInNewWindow = { Link l -> l.isOpenInNewWindow }
@Shared Closure linkIsHttps = { Link l -> l.url.startsWith("https") }

expect:
    1 * linkService.checkStuff(linkIsHttps) >> true
    1 * linkService.checkStuff(linkIsOpenInNewWindow) >> false

当我运行这段代码时,它总是:

Too few invocations for:

1 * linkService.checkStuff(linkIsHttps) >> true   (0 invocations)

Unmatched invocations (ordered by similarity):

1 * linkService.checkStuff(Link@1234)

有什么方法可以实现这一点并在 spock 中创建和使用命名的可重用闭包?

假规格:

@Grab('org.spockframework:spock-core:1.0-groovy-2.4')
@Grab('cglib:cglib:3.1') 
@Grab('org.ow2.asm:asm-all:5.0.3') 

import spock.lang.Shared
import spock.lang.Specification

class Test extends Specification {

    LinkService linkService = Mock(LinkService)

    @Shared
    Closure openInNewWindow = { it.isOpenInNewWindw()}

    @Shared
    def httpsLink = { Link l -> l.url.startsWith("https") }

    @Shared
    def secureLink = new Link(
        url: "https://exmaple.com",
        openInNewWindw: false
    )

    @Shared
    def externalLink = new Link(
        url: "http://exmaple.com",
        openInNewWindw: true
    )

    def "failing closure test"() {
        when:
        def secureLinkResult = linkService.doStuff(secureLink)
        def externalLinkResult = linkService.doStuff(externalLink)

        then:
        secureLinkResult == 1
        externalLinkResult == 2

        1 * linkService.doStuff(httpsLink) >> 1
        1 * linkService.doStuff(openInNewWindow) >> 2
    }

    def "passing closure test"() {
        when:
        def secureLinkResult = linkService.doStuff(secureLink)
        def externalLinkResult = linkService.doStuff(externalLink)

        then:
        secureLinkResult == 1
        externalLinkResult == 2

        1 * linkService.doStuff({Link l -> l.url.startsWith("https")}) >> 1
        1 * linkService.doStuff({Link l -> l.openInNewWindw}) >> 2
    }
}

class Link {
    String url
    boolean openInNewWindw
}

interface LinkService {
    int doStuff(Link link)
}

【问题讨论】:

    标签: groovy spock


    【解决方案1】:

    你可以这样写:

    def "failing closure test"() {
        when:
        def secureLinkResult = linkService.doStuff(secureLink)
        def externalLinkResult = linkService.doStuff(externalLink)
    
        then:
        secureLinkResult == 1
        externalLinkResult == 2
    
        1 * linkService.doStuff({ httpsLink(it) }) >> 1
        1 * linkService.doStuff({ openInNewWindow(it) }) >> 2
    }
    

    一些解释可以找到in this thread

    【讨论】:

    • 不。它不工作。不执行关闭。 def httpsLink = { Link l -> {print("asd"); return l.url.startsWith("https")} } 并且不打印 asd 文本。看起来关闭没有执行
    • 要使这项工作正常工作,您需要1 * linkService.doStuff({ httpsLink(it) }) 不完全是我所希望的,但它是一些东西;)
    • 我不确定为什么打印不起作用,但是当我将secureLink定义更改为应该破坏测试的东西(eq.url: "http://exmaple.com")然后测试失败,但没有打印任何东西。跨度>
    • 很奇怪def secureLink = new Link(url: "http://exmaple.com", openInNewWindw: false) (no https) 和验证是:1 * linkService.doStuff({ httpsLink }) >> 1 然后JUnit 4 Runner, Tests: 1, Failures: 0, Time: 167 它会一直通过,除非我用{httpsLink(it)} 验证它。我不确定发生了什么。我正在使用带有 java8 的 groovy 2.4.3
    • 是的,你是对的。对不起,令人困惑的评论。使用{ httpsLink(it) } 作为匹配器正在工作,因此您可以将答案标记为正确。
    猜你喜欢
    • 1970-01-01
    • 2015-03-20
    • 2015-08-03
    • 2022-06-11
    • 1970-01-01
    • 2021-09-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多