是否可以动态生成 Spock 测试方法?

Is it possible to dynamically generate Spock test methods?

我有很多重复的测试,我想以某种方式抽象它们。辅助方法一直很有用,但在一定程度上是有用的。如果我能以某种方式在我的 Specification 中以编程方式生成测试方法,我将能够删除大量复制粘贴代码。

具体来说,我正在测试RPC层的方法。如果不以某种方式调用大多数方法,它们肯定会失败。所以我有像这样的 Spock 测试方法:

def observer = Mock(StreamObserver)
def rpc = new UserServiceRpc()

def "draftToOutbox: should fail when called without parent"() {

    def request = draftToOutboxRequest().toBuilder().clearParent().build()

    when:
    rpc.draftToOutbox(request, observer)

    then:
    1 * observer.onError(_)
    1 * observer.onCompleted()
}

def "outboxToDraft: should fail when called without parent"() {

    def request = outboxToDraftRequest().toBuilder().clearParent().build()

    when:
    rpc.outboxToDraft(request, observer)

    then:
    1 * observer.onError(_)
    1 * observer.onCompleted()
}

不幸的是,我不熟悉 Groovy 的元编程(编译时 AST 转换)功能,我不确定如何做到这一点,是否可能,以及这是否是个好主意.一方面我有一些复制粘贴,但另一方面我的测试非常可读。不过,我倾向于两全其美:没有复制粘贴的可读性。

在这种情况下,您可以将 Data Driven Testing 与一些 groovy 内容一起使用,如下所示:

@Unroll
def "#method: should fail when called without parent"() {
    given:
    def request = "$methodToGetRequest"().toBuilder().clearParent().build()
    when:
    rpc."$methodToTest"(request, observer)
    then:
    1 * observer.onError(_)
    1 * observer.onCompleted()

    where:
    methodToTest    | methodToGetRequest
    'draftToOutbox' | 'draftToOutboxRequest'
    'outboxToDraft' | 'outboxToDraftRequest'
}

编辑

一个使用方法指针的例子:

@Shared
String subjectToTest

def setupSpec() {
    subjectToTest = "sTring To Test"
}

def "test using method pointers"() {
    when:
    def result = methodPointer()
    then:
    result == expectecResult
    where:
    expectecResult   | methodPointer
    'STRING TO TEST' | subjectToTest.&toUpperCase
    'string to test' | subjectToTest.&toLowerCase
}