Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you mock out a static method of a domain object in Grails?

have a Grails domain object that has a custom static function to grab data from the database

class Foo {
    /* member variables, mapping, constraints, etc. */

    static findByCustomCriteria(someParameter, List listParameter) {
        /* code to get stuff from the database... */

        /*
            Return value is a map
            ["one": "uno", "two": "due", "three": "tre"]
        */
    }

}

The static function findByCustomCriteria uses createCriteria() to build the query that pulls data from the Foo table, which means mockDomain(Foo) does not work properly when unit testing. What I'm trying to do to work around this is use one of the general purpose methods of mocking to mock out findByCustomCriteria, but I can't get the syntax quite right.

I have a controller BarController that I'm trying to test, and buried in the call to BarController.someFunction() there is a call to Foo.findByCustomCriteria().

class BarControllerTest extends ControllerUnitTestCase {

    protected void setUp() {
        super.setUp()
    }

    protected void tearDown() {
        super.tearDown()
    }

    void testSomeFunction() {

        /* Mocking for Foo goes here */

        assertEquals("someValue", controller.someFunction())
    }
}

What would be a way to mock this out?

I've tried using new MockFor(), mockFor(), and metaClass, but I can't get it to work.


Edit:

Every time I tried to mock this out, I tried to mock it like so...

Foo.metaClass.'static'.findByCustomCriteria = { someParam, anotherParam ->
    ["one": "uno", "two": "due", "three": "tre"]
}

I guess I didn't include enough information initially.

like image 341
haydenmuhl Avatar asked Oct 30 '10 00:10

haydenmuhl


2 Answers

I've encountered this scenario more than once, you need to modify the static metaClass of Foo:

Foo.metaClass.'static'.findByCustomCriteria = { someParameter, List listParameter ->
    ["one": "uno", "two": "due", "three": "tre"]
}

Typically I'll put it in the test setup, so I don't forget when it needs to be applied.

like image 168
Stephen Swensen Avatar answered Nov 06 '22 03:11

Stephen Swensen


In Grails 2.0 and higher, you can use the GrailsMock class like this

def mockControl = new GrailsMock(MyDomainClass)
mockControl.demand.static.get() {id -> return null}  // Static method
...
mockControl.verify()

See here.

like image 27
Behrang Avatar answered Nov 06 '22 03:11

Behrang