3

I am new to groovy and Spock.

I'm trying to create a generic method for mocking objects in my system.

the problem

I'm trying to create a function that will get an object and dynamically mock the functions I want in the object. the function gets a map of functions with data when to mock each of one them and what to return. the functions return an error.

I created a class

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

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

the mocking function is:

    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
}

I'm creating the object :

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)

the code above returns the following exception:

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)

the line that fails

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

1 Answer 1

3

In Spock Framework, you can't create a mock in such a dynamic fashion. Spock has its own compiler (AST Transformation to be precise) which creates an executable test code. Only when in interaction section, does it recognize "_" as a wildcard symbol and ">>" operator to return a fixed value. That's why you get that exception. Because "_" wildcard is not in an interaction section. I'd suggest writing your test similar to the following:

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"
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

thanks @Dmitry, I tried something like you wrote before I went on the generic way. Just wanted to try a generic way. I think it's not possible

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.