Spock @ConfineMetaClassChanges annotation made writing grails unit test easier

10 / Jan / 2014 by Amit Jain 0 comments

Grails version 2.0 and above made unit testing much simpler with so many new annotations introduced. However if you wanted to mock a specific method of a class whose method is being tested or you wanted to create a stub of the class already annotated by @Mock, things would become difficult. So I always ended up mocking methods via metaclass as given below:

class UserService {

 void sampleMethod(){
   ....
   subMethod()
 }

 void subMethod(){
  ...
 }
}

@TestFor(UserService)
class UserServiceSpec extends Specification {

 def sampleMethodSpec(){
  ....
  service.metaclass.subMethod = {}
  ....
 }
}

But this may have adverse effects on other test cases of same class UserService that follows it or used in some other test cases. To avoid such situation, one must reset that method added to the metaclass once the test case finishes, but thats again a hassle, leads to noisy code and we could easily forget to reset it back.

One better alternative that I found to tackle above mentioned problem is @ConfineMetaClassChanges annotation provided by Spock framework. It restores the metaclass to its previous state.

Just add the following annotation to your class and use metaclass without any fear of adverse effects.

import spock.util.mop.ConfineMetaClassChanges
@ConfineMetaClassChanges([UserService])

The above annotation can be defined at both class and method level, which allows the metaclass cleanup accordingly i.e restore metaclass back to its previous state after executing all the test cases of that class or after every single test case that gets executed.

Cheers!!
Amit Jain
amit@intelligrape.com

FOUND THIS USEFUL? SHARE IT

Leave a comment -