验证构造函数中的方法调用

Verify method call in constructor

我有以下规格:

@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.*

class Whatever extends Specification {

    def "bind view to object in constructor" () {
        given:
        def view = Mock(View)
        def binder = Mock(Binder)

        when:
        def holder = new Holder(binder, view)

        then:
        1 * binder.bind(holder, view)
    }
}

class Binder {
    def bind(Holder holder, View view) {}
}
class View {}

class Holder {
    Holder(Binder binder, View view) {
        binder.bind(this, view)
    }
}

失败:

groovy.lang.MissingPropertyException: No such property: holder for class: Whatever

在以下行中:

1 * binder.bind(holder, view)

then 块中。

我知道它为什么会失败,因为 thenwhen 块之前计算。问题是,它如何在没有任何棘手的解决方法的情况下测试此 binder.bind() 构造函数调用?

您可以简单地在 given: 块中定义 holder

class Whatever extends Specification {
    def "bind view to object in constructor" () {
        given:
        def view = Mock(View)
        def binder = Mock(Binder)
        def holder

        when:
        holder = new Holder(binder, view)

        then:
        1 * binder.bind(holder, view)
    }
}

然而,失败了:

Too few invocations for:

1 * binder.bind(holder, view)   (0 invocations)

Unmatched invocations (ordered by similarity):

1 * binder.bind(Holder@519b27f6, Mock for type 'View' named 'view')

因为当 交互 被验证时 holder 尚未分配。所以要测试交互,最好这样做:

class Whatever extends Specification {
    def "bind view to object in constructor" () {
        given:
        def view = Mock(View)
        def binder = Mock(Binder)

        when:
        new Holder(binder, view)

        then:
        1 * binder.bind(!null, view) // or 1 * binder(_ as Holder, view)
    }
}

如果我们仍然想检查 holder 我们需要一个 closure to capture the arguments:

def "bind view to object in constructor" () {
    given:
    def view = Mock(View)
    def binder = Mock(Binder)
    def holder
    def argHolder

    when:
    holder = new Holder(binder, view)

    then:
    1 * binder.bind(*_) >> { arguments ->            
        argHolder = arguments[0]
        assert view == arguments[1]
    }
    assert argHolder == holder
}