Friday Repost: Remove Groovy MetaClass methods

The Friday Repost series are copies from my earlier writings. Since I don’t want to loose them, and they might prove useful to others, I’m reposting them on this blog

Whenever you are using metaclasses in Groovy or Grails unit tests, you might use Groovy’s metaClass power to mock the behavior of methods. However, Grails doesn’t fork the JVM for each test, so a nice side effect of this is that the mocked method will be available for the complete lifetime of the VM. Since Grails first executes unit tests (the test which usually contain the mocked code), and then followed by the integration tests, these tests can fail because you are maybe still using a mocked version of the method instead of the real one! This can often happen when mocking Grails methods, like dynamic finders, or named queries. The trick is to clean up these methods.

This is done by registering the metaClass when extending GrailsUnitTestCase. You’ll have to call the registerMetaClass(clazz) method, which does the following internally:

You can use this code in your tests in the following way, for example in the UserTests.groovy:

This way, the User class is registered with Grails to be cleaned up afterwards. This is done automatically in the teardown of the test, so you’re sure that no custom defined methods are available after running the test.

So, beware that whenever you use Groovy’s meta magic, be also sure to clean it up afterwards, since it might affect other parts of the code. You can check out my other blog post for a good solution to not forget the cleanup part!

Groovy MetaClass Magic in Unit Tests

As you may or may not know, Groovy has the concept of MetaClasses. MetaClasses enable you to add or change methods at runtime. This is especially handy when doing some mocking during a unit test (or, in our case, GrailsUnitTestCases). By mocking methods, you can mock out certain dependencies or behavior which you might not want during a unit test. An example:

In this case, if you want to test the logic of the PersonAdapter without using the complex operations in the service, on way to test this by using some MetaClass magic, as can be seen below:

While this might be not be the optimal example or test (you might consider using Mocks instead), there’s a flaw in this test. Since the complexOperation is now metaClassed on the class level, instead of on the object, it means that future tests will also be affected, including Integration tests. This might lead to some very unexpected behaviors, which are sometimes hard to track down.

There are two ways to ‘fix’ this:

  1. Always call the super.tearDown() in tests. This will reset the Groovy meta registry to it’s normal state. However, you need to explicitly call ‘registerMetaClass’ in tests to allow Grails to clean this up. If you forget this, you’re metaClass change can affect other tests too. To prevent that, we have option 2.
  2. Use the MetaClassMixin.

The MetaClassMixin is a simple class we use in our project to automatically register metaClasses in the GroovySystem’s MetaClassRegistery. Since we are using only the MetaClassMixin to do metaclass magic instead of doing it directly on classes, we can never forget to register the class anymore. This has saved us in many cases. An example usage can be seen below:

Using the MetaClassMixin, you no long have to worry about registering your MetaClassed classes, or, more importantly forgetting to register them! Below, you can find the source of the MetaClassMixin (this mixin has been written by Levi Hoogenberg, so credits for that!). Feedback on this welcome of course!

Happy metaClassing!