ASSUNTO
Continuando e completando o assunto do card de 11 meses atrás Desfazer alterações no metaclass em testes de unidade (leia-o primeiro):
CONCLUSÕES
- 
Teste que herda da classe GrailsUnitTestCase na implementação do Grails 2.2.4 não sofre com o problema de metaclass alterado em testes de unidade desde que seja utilizada super.tearDown() em sua implementação. Lembrando que caso você não sobrescreva o método void tearDown() este comportamento herdado já é executado por padrão. Perceba que o uso de registerMetaClass(Classe) (implementação exclusiva de GrailsUnitTestCase) de qualquer forma depende do super.tearDown() e não faz nenhum milagre sozinho, já o super.tearDown() sozinho faz. 
- 
Teste que herda da classe GMockTestCase na implementação do abandonado Gmock 0.8.3 já passa a sofrer com o problema de metaclass alterado em testes de unidade. A solução é a apresentada no card anterior, com o uso da seguinte chamada no final do próprio método de teste ou no tearDown da classe: GroovySystem.metaClassRegistry.removeMetaClass(Classe)
- 
Teste que herda da classe GroovyTestCase (que por sinal é a superclasse de GMockTestCase) também sofre com o problema de metaclass alterado em testes de unidade. A solução também é o uso do removeMetaClass no final do próprio método de teste ou no tearDown da classe. 
- 
Teste que herda da classe Specification/UnitSpec/IntegrationSpec na implementação do spock 0.7 também sofre com o problema de metaclass alterado em testes de unidade. A solução também é o uso do removeMetaClass, que aqui pode ser utilizada no próprio teste na seção cleanup, ou em um dos métodos cleanupSpec ou cleanup da classe, de acordo com o escopo necessário. 
- 
Teste que não herda nenhuma classe e usa a estrutura de anotações @TestFor/@Mock/@WithGMock, segundo o analisado, não sofre com o problema de metaclass alterado em testes de unidade de forma alguma. Aparentemente cada teste, seja na mesma classe ou não, é completamente independente quanto aos metaclass alterados. Na "desconfiança" seria indicado o uso da chamada removeMetaClass em (a) um método qualquer com a anotação @After ou (b) no método tearDown para evitar problemas futuros. 
COMPROVAÇÕES
Crie as seguintes classes e mande executar os testes de todas elas de uma vez só.
GrailsUnitTestCase e GMockTestCase e GroovyTestCase
class ArquivoCausaBug1Tests extends GrailsUnitTestCase {
    void tearDown() {
        super.tearDown() //Necessário para impedir problemas
        // processamento adicional qualquer ...
    }
    void testA() {
        boolean replaceCalled = false
        String.metaClass.replace = { CharSequence a, CharSequence b ->
            replaceCalled = true
            return 'metaclass usado'
        }
        assertEquals 'metaclass usado', 'aba'.replace('b', 'a')
        assertEquals true, replaceCalled
    }
    void testB() {
        assertEquals 'aaa', 'aba'.replace('b', 'a')
    }
}
class ArquivoCausaBug2Tests extends GMockTestCase {
    void tearDown() {
        super.tearDown()
        GroovySystem.metaClassRegistry.removeMetaClass(String) //Necessário para impedir problemas
    }
    void testA() {
        boolean replaceCalled = false
        String.metaClass.replace = { CharSequence a, CharSequence b ->
            replaceCalled = true
            return 'metaclass usado'
        }
        assertEquals 'metaclass usado', 'aba'.replace('b', 'a')
        assertEquals true, replaceCalled
    }
    void testB() {
        assertEquals 'aaa', 'aba'.replace('b', 'a')
    }
}
class ArquivoCausaBug3Tests extends GroovyTestCase {
    void tearDown() {
        super.tearDown()
        GroovySystem.metaClassRegistry.removeMetaClass(String) //Necessário para impedir problemas
    }
    void testA() {
        boolean replaceCalled = false
        String.metaClass.replace = { CharSequence a, CharSequence b ->
            replaceCalled = true
            return 'metaclass usado'
        }
        assertEquals 'metaclass usado', 'aba'.replace('b', 'a')
        assertEquals true, replaceCalled
    }
    void testB() {
        assertEquals 'aaa', 'aba'.replace('b', 'a')
    }
}
class ArquivoIndependenteSofreBugTests extends GrailsUnitTestCase {
    void testB() {
        assertEquals 'aaa', 'aba'.replace('b', 'a')
    }
}
Specification / UnitSpec / IntegrationSpec
class ArquivoCausaBugSpec extends UnitSpec {
    void 'test A'() {
        setup:
        boolean replaceCalled = false
        String.metaClass.replace = { CharSequence a, CharSequence b ->
            replaceCalled = true
            return 'metaclass usado'
        }
        expect:
        'metaclass usado' == 'aba'.replace('b', 'a')
        replaceCalled
        cleanup:
        GroovySystem.metaClassRegistry.removeMetaClass(String) //Necessário para impedir problemas
    }
    void 'test B'() {
        expect:
        'aaa' == 'aba'.replace('b', 'a')
    }
}
class ArquivoIndependenteSofreBugSpec extends UnitSpec {
    void 'test B'() {
        expect:
        'aaa' == 'aba'.replace('b', 'a')
    }
}
Anotações
@TestFor(DomainClass)
@WithGMock
class ArquivoCausaBug3Tests {
    void testA() {
        assertEquals 'aaa', 'aba'.replace('b', 'a')
    }
    void testB() {
        boolean replaceCalled = false
        String.metaClass.replace = { CharSequence a, CharSequence b ->
            replaceCalled = true
            return 'metaclass usado'
        }
        assertEquals 'metaclass usado', 'aba'.replace('b', 'a')
        assertEquals true, replaceCalled
    }
    void testC() {
        assertEquals 'aaa', 'aba'.replace('b', 'a')
    }
}
FONTES ORIGINAIS DE ESTUDO (além dos arquivos próprios criados)