One of the handy features of Groovy is to change the behavior of classes using MOP (Meta-Object Protocol). We change the metaClass property of a class to alter an implementation. You can for example override a static method of a class. See the example below:

class UserSpec extends Specification {

    def “test user”() {
        given:
        // we can mock static methods...
        User.metaClass.static.findByName = { name ->
            new User(name: ‘Albert’) }
        when:
        User user = User.findByName(‘Albert’)

        then:
        user.name == ‘Albert’

        when:
        // .. but also non-static methods
        user.metaClass.getName = { return ‘Dries’ }

        then:
        user.name == ‘Dries’
    }

}

However this way of mocking has a nasty side effect. Since we apply changes on the User on class level, the changes are also applied in all our other test cases. This can have some unexpected behavior in your other tests To prevent this Spock has introduced the @ConfineMetaClassChanges annotation. This annotation makes sure the class will return to its original state when it was used in our test. See the example below:

@ConfineMetaClassChanges([User]) // you can add multiple classes in the annotation
class UserSpec extends Specification {
...
}

Be aware: this means when some other test did changes to the User class without using @ConfineMetaClassChanges, these changes will be still applicable when the test which has @ConfineMetaClassChanges restores the User class to its old state.

shadow-left