Dahlia Bock

27Aug/112

Grails: Mocking domain classes in controller specs

I've been working in the Grails space for the last few months and after having done some work in Rails before, I've found Grails to be severely frustrating. One of the problems we faced when writing specs for our controllers is that the available testing frameworks (e.g. Spock) doesn't really have the capability to mock out all domain methods (instance and static) properly when they are called from within an event (e.g. beforeUpdate, beforeDelete).

One way that Ben and I tried was to use Groovy's metaClass to essentially mock out those methods that were called within the domain class events. For example, given the Contact domain class:

public class Contact {
    def beforeUpdate = {
        someLocalMethod()
    }
}

And the ContactControllerSpec:

public class ContactControllerSpec extends ControllerSpec {
    def "should update contact"() {
        given:
        def contacts = [new Contact(name: "John Smith", phone: "123456789")]
        mockDomain(Contact, contacts)
 
        when:
        controller.update()
 
        then:
        ...
    }
}

This test will throw an exception saying that it doesn't recognize the call to

someLocalMethod

So we had to mock it out:

registerMetaClass(Contact)
Contact.metaClass.someLocalMethod = {}

The call to

registerMetaClass

ensures that any modifications you've made to the class gets cleaned up at the end of every test.

If someone else knows of a better way to do this, I'd would much appreciate some tips.

Comments (2) Trackbacks (0)
  1. Why do you have to mock your domain objects?

    • Most controller actions interact with the model eventually (save/delete/update) and those methods are dynamically added in Grails, so only found at runtime. Poop.


Leave a comment

(required)

No trackbacks yet.