Wednesday, February 10, 2010

Stub static method on domain class in Grails explained

Since Grails 1.1 the unit test capability has been greatly improved for pretty much anything you can imagine in Grails from domain class to controller even taglibs can be easily tested in plain old junit with the help of GrailsUnitTestCase and many of it's cousins such as ControllerUnitTestCase specialized in different aspects of the framework.

However the fantastic mocking framework is not without its boundary. The mockDomain method provided by GrailsUnitTestCase has its limit, it does not provide the capability to fully mock GORM dynamic finders as well as criteria and executeQuery methods. Luckily the test framework also provide the ability to mock any method regular or static using mockFor() method (details) however it comes short when you have static query method created on domain class. Imagine the following example:


class Foo{
...

static def listAllAwesomeFoo(keyword, params) {
Foo.executeQuery('''select f from Foo as f
inner join f.tags as t
where f.awesome = true and t.keyword = ?''',
[keyword],
params)
}
}

class FooService {
def doSomethingUseful(){
def awesomeFoos = Foo.listAllAwesomeFoo('something', [max:10])
....
}
}


Now to test the FooService you need the ability to stub or mock the Foo.listAllAwesomeFoo() method and since its a static method there is really no easy way to do it even with Grails test framework; or is there? This is where Groovy MOP can save you a lot of grief and time. To stub this kind of static method all you need to do in Groovy is add the following code before your test code:


Foo.metaClass.static.listAllAwesomeFoo = {keyword, params -> [foo1, foo2] }


Thats it. Now you can happily test all your service logic without worrying about stubbing the whole database to run the HQL. Later on you can always isolate and use integration test with in-memory database to test the HQL separately.

No comments: