Polluted Mocked Test Data from Unit in Integration Test using Grails 1.3.5

Recently the REWOO source code had some unpredictable test results in your grails test environment running unit and integration tests together. We’re using grail 1.3.5 and are running test-app to execute all our all unit and integration tests at once.

Behaviour: After running all unit tests with success, the first integration test failed. Running the failed test separately succeeds. Ignoring the first integration test did not help because the next integration test failed. Further, executing unit tests with test-app -unit and than integration tests test-app -integration did not show that error.

Inspection: The debugger showed that some test data of your model data from unit test were available in the first integration test and caused the error. What? Unit test data pollutes data in integration test? Hibernate’s PersistenceContext was empty. SecondLevelCache was empty. Next integration tests were cleaned up correctly.

After some time it leads us to a bug entry GRAILS-7514 mentioned “testdata from unit test is available in integration test“. It describes an issue with domain model hierarchy and their mocks in unit tests which are not cleanup correctly. So some metaClass assignments are still alive in following integration tests. Resolution from Graeme Rocher was a kind of “works on my machine” with Grails 2.0. But we have Grails 1.3.5!

Solution: True, we had a bunch of mocked domain models and our domain models have a class hierarchy up to four levels. Digging deeply in Grails test code we found a snippet in grails-1.3.5/src/test/grails/test/MetaTestHelper.groovy which deals with the MetaClassRegistry of Grails. All we had to do is to clean it in the unit tearDown() method of our base unit test class to get clean domain classes. The spook disappeared.

Use following code in your unit tests if you experience the same:

public class RewooUnitTestCase extends GrailsUnitTestCase {

    def tearDown() {
        // ....
        mockCleanup()
    }

    /**
     * De-mock class hierarchies of RewooType and RewooElement
     *
     * This cleanup is required to clean metaClass assignments of mocks with class
     * hierarchies. Otherwise it would pollute following tests. In particular, it
     * would pollute the first integration test after a unit test.
     *
     * This solution was inspired by grails' MetaTestHelper.groovy
     *
     * See also http://jira.grails.org/browse/GRAILS-7514
     */
    private mockCleanup() {
        List classes = [RewooType.class, ...]
        classes += [RewooElement.class, ...]
        classes.each { clazz ->
            GroovySystem.metaClassRegistry.removeMetaClass clazz
        }
    }

    // ...

}