【问题标题】:Groovy Spread Operator with Spock Framework Mock "_" option inside带有 Spock 框架模拟“_”选项的 Groovy 扩展运算符
【发布时间】:2019-01-27 09:00:28
【问题描述】:

我是 groovy 和 Spock 的新手。

我正在尝试在我的系统中创建一个用于模拟对象的通用方法。

问题

我正在尝试创建一个函数,该函数将获取一个对象并动态模拟对象中我想要的函数。 该函数获取一个函数映射,其中包含数据何时模拟它们中的每一个以及返回什么。 函数返回错误。

我创建了一个类

    class MetaData {
    Object[] argTypes
    def returnValue
    Object[] argsMatchers

    MetaData(Object[] argTypes, returnValue, Object[] argsMatchers) {
        this.argTypes = argTypes
        this.returnValue = returnValue
        this.argsMatchers = argsMatchers
    }
}

模拟函数是:

    def mockFunctionTestData(Map overrides = [:], def clazz){
    def args = Mock(clazz)
    overrides.each { String key, value ->
        Object[] argTypes = value.argTypes
        if(args.metaClass.respondsTo(args, key, argTypes).size() == 1){
            def methodToGetRequest = key
            def argsMatchers = value.argsMatchers
            def returnValue = value.returnValue

            args."$methodToGetRequest"(*argsMatchers) >> returnValue
        } else {
            println "Error: Trying to add property that doesn't exist"
        }
    }
    return args
}

我正在创建对象:

def functionData = new MetaData([Date, Date, List, boolean] as Object[],
      meas,
      [_ as Date, _ as Date, new ArrayList<>(), true] as Object[]) //the line that fails
def dogDAO = [getDogData: functionData]


def testDog= mockFunctionTestData(dogDAO , Dog)

上面的代码返回以下异常:

org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object '_' with class 'org.spockframework.lang.Wildcard' to class 'java.util.Date' due to: groovy.lang.GroovyRuntimeException: Could not find matching constructor for: java.util.Date(org.spockframework.lang.SpreadWildcard)

失败的那一行

[_ as Date, _ as Date, new ArrayList<>(), true] as Object[]) 

【问题讨论】:

    标签: unit-testing groovy mocking spock


    【解决方案1】:

    在 Spock 框架中,您无法以这种动态方式创建模拟。 Spock 有自己的编译器(准确地说是 AST 转换),它可以创建可执行的测试代码。只有在交互部分,才会将“_”识别为通配符,将“>>”运算符识别为返回固定值。这就是为什么你得到那个例外。因为“_”通配符不在交​​互部分。我建议您编写类似于以下内容的测试:

    class DogSpec extends Specification {
        def "test the dog"() {
            when:
            def dog = Mock(Dog) {
                1 * getDogData(_ as Date, _ as Date, new ArrayList<>(), true) >> "Bark"
            }
    
            then:
            dog.getDogData(new Date(), new Date(), [], true) == "Bark"
        }
    }
    

    【讨论】:

    • 感谢@Dmitry,在我采用通用方式之前,我尝试了类似你写的东西。只是想尝试一种通用的方式。我认为这是不可能的
    猜你喜欢
    • 2019-02-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-22
    • 2022-06-30
    • 2021-04-09
    • 1970-01-01
    相关资源
    最近更新 更多