ttt
ttt

Reputation: 219

How to mock obj.&method in groovy/grails

Code below. I would like to use the obj.&method thing to pass around a reference to it. However, when trying to test that, mocking it doesn't work. Is there something in the test I can do to make it work?

The result of running the test is it throws the exception "should not get here".

import grails.test.mixin.TestFor

@TestFor(SomeController)
class SomeControllerTest {
    void testSomething() {
        def control = mockFor(SomethingElse)
        control.demand.someMethod(1) { int num, String str, Map another, List param ->
            println 'worked'
        }
        controller.obj = control.createMock()

        controller.underTest()

        control.verify()
    }
}

class SomeController {
    SomethingElse obj

    void underTest() {
        otherCall(obj.&someMethod) // **
    }

    void otherCall(toRun) {
        String result = toRun(1, 'blah', null, null) // ** doesn't call mock here
    }
}

class SomethingElse {
    String someMethod(int num, String str, Map another, List param) {
        throw new RuntimeException('should not get here')
    }
}

Upvotes: 1

Views: 231

Answers (1)

dmahapatro
dmahapatro

Reputation: 50245

Yes, don't mock SomethingElse. Use ExpandoMetaClass instead.

void testSomething() {
    SomethingElse.metaClass.someMethod = {int num, String str, Map another, 
                                             List param ->
        println 'worked'
    }

    controller.obj = new SomethingElse()

    controller.underTest()
}

with the price of loosing the mock control.

A roundabout way would be to mock otherCall() as well

void testSomething() {
    def control = mockFor(SomethingElse)
    control.demand.someMethod(1) { int num, String str, Map another, 
                                        List param ->
        println 'worked'
    }

    def obj = control.createMock()

    controller.metaClass.otherCall = {Closure clos -> 
        delegate.obj.someMethod(1, 'blah', null, null)
    }

    controller.obj = obj
    controller.underTest()
    control.verify()
}

This way you can verify the mock control. But I am still skeptical about using mock objects and MethodClosure together.

Upvotes: 1

Related Questions