我如何使用 Spock 中的 Mock 在 Grails 中进行测试?

How do I use Mock in Spock to do tests in Grails?

我正在尝试对域 class 使用模拟,但在 findBy 中不起作用,显示 class 为空。

上次报这个错:

"C:\Program Files\Java\jdk1.8.0_144\bin\java" -ea -Didea.test.cyclic.buffer.size=1048576 "-javaagent:C:\Users\pedro.borborema-nub\AppData\Roaming\JetBrains\IntelliJ IDEA 2017.2.5\lib\idea_rt.jar=50871:C:\Users\pedro.borborema-nub\AppData\Roaming\JetBrains\IntelliJ IDEA 2017.2.5\bin" -Dfile.encoding=UTF-8 -classpath C:\Users\Administrador\AppData\Local\Temp\classpath2.jar com.intellij.rt.execution.junit.JUnitStarter -ideVersion5 -junit4 "colaborar.pagamentos.PagamentoServiceSpec,teste taxa"
2018-01-10 14:36:15 [main] ERROR g.a.s.c.pagamentos.PagamentoService - Erro ao gerar documentoInfo: java.lang.IllegalStateException: Either class [colaborar.domains.financeiro.CrParcela] is not a domain class or GORM has not been initialized correctly or has already been shutdown. If you are unit testing your entities using the mocking APIs
    at org.grails.datastore.gorm.GormEnhancer.stateException(GormEnhancer.groovy:159)
    at org.grails.datastore.gorm.GormEnhancer.findStaticApi(GormEnhancer.groovy:153)
    at org.grails.datastore.gorm.GormEnhancer.findStaticApi(GormEnhancer.groovy)
    at org.grails.datastore.gorm.GormEntity$Trait$Helper.currentGormStaticApi(GormEntity.groovy:1315)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:93)
    at org.codehaus.groovy.runtime.callsite.StaticMetaMethodSite$StaticMetaMethodSiteNoUnwrapNoCoerce.invoke(StaticMetaMethodSite.java:151)
    at org.codehaus.groovy.runtime.callsite.StaticMetaMethodSite.call(StaticMetaMethodSite.java:91)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)
    at colaborar.domains.financeiro.CrParcela.currentGormStaticApi(CrParcela.groovy)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:93)
    at org.codehaus.groovy.runtime.callsite.StaticMetaMethodSite$StaticMetaMethodSiteNoUnwrapNoCoerce.invoke(StaticMetaMethodSite.java:151)
    at org.codehaus.groovy.runtime.callsite.StaticMetaMethodSite.call(StaticMetaMethodSite.java:91)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
    at org.codehaus.groovy.runtime.callsite.StaticMetaClassSite.call(StaticMetaClassSite.java:58)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:117)
    at org.grails.datastore.gorm.GormEntity$Trait$Helper.staticMethodMissing(GormEntity.groovy:734)
    at org.grails.datastore.gorm.GormEntity$Trait$Helper$staticMethodMissing[=10=].call(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:141)
    at colaborar.domains.financeiro.CrParcela.staticMethodMissing(CrParcela.groovy)
    at colaborar.domains.financeiro.CrParcela$staticMethodMissing.callStatic(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallStatic(CallSiteArray.java:56)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callStatic(AbstractCallSite.java:194)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callStatic(AbstractCallSite.java:214)
    at colaborar.domains.financeiro.CrParcela.$static_methodMissing(CrParcela.groovy)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:93)
    at groovy.lang.MetaClassImpl.invokeStaticMissingMethod(MetaClassImpl.java:1496)
    at groovy.lang.MetaClassImpl.invokeStaticMethod(MetaClassImpl.java:1484)
    at org.codehaus.groovy.runtime.callsite.StaticMetaClassSite.call(StaticMetaClassSite.java:53)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)
    at colaborar.pagamentos.PagamentoService.getDocumentoInfo(PagamentoService.groovy:62)
    at colaborar.pagamentos.PagamentoService$getDocumentoInfo.call(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)
    at colaborar.pagamentos.PagamentoServiceSpec.$spock_feature_0_6(PagamentoServiceSpec.groovy:75)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.spockframework.util.ReflectionUtil.invokeMethod(ReflectionUtil.java:153)
    at org.spockframework.runtime.model.MethodInfo.invoke(MethodInfo.java:84)
    at org.spockframework.runtime.BaseSpecRunner.invokeRaw(BaseSpecRunner.java:480)
    at org.spockframework.runtime.BaseSpecRunner.invoke(BaseSpecRunner.java:463)
    at org.spockframework.runtime.BaseSpecRunner.runFeatureMethod(BaseSpecRunner.java:405)
    at org.spockframework.runtime.BaseSpecRunner.doRunIteration(BaseSpecRunner.java:324)
    at org.spockframework.runtime.BaseSpecRunner.invoke(BaseSpecRunner.java:309)
    at org.spockframework.runtime.extension.MethodInvocation.proceed(MethodInvocation.java:88)
    at org.spockframework.runtime.extension.builtin.AbstractRuleInterceptor.evaluate(AbstractRuleInterceptor.java:37)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite$PojoCachedMethodSiteNoUnwrapNoCoerce.invoke(PojoMetaMethodSite.java:233)
    at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite.call(PojoMetaMethodSite.java:56)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:117)
    at grails.test.runtime.TestRuntimeJunitAdapter.evaluate(TestRuntimeJunitAdapter.groovy:46)
    at org.spockframework.runtime.extension.builtin.TestRuleInterceptor.intercept(TestRuleInterceptor.java:38)
    at org.spockframework.runtime.extension.MethodInvocation.proceed(MethodInvocation.java:87)
    at org.spockframework.runtime.BaseSpecRunner.invoke(BaseSpecRunner.java:471)
    at org.spockframework.runtime.BaseSpecRunner.runIteration(BaseSpecRunner.java:288)
    at org.spockframework.runtime.BaseSpecRunner.initializeAndRunIteration(BaseSpecRunner.java:278)
    at org.spockframework.runtime.BaseSpecRunner.runSimpleFeature(BaseSpecRunner.java:269)
    at org.spockframework.runtime.BaseSpecRunner.doRunFeature(BaseSpecRunner.java:263)
    at org.spockframework.runtime.BaseSpecRunner.invoke(BaseSpecRunner.java:246)
    at org.spockframework.runtime.BaseSpecRunner.invokeRaw(BaseSpecRunner.java:480)
    at org.spockframework.runtime.BaseSpecRunner.invoke(BaseSpecRunner.java:463)
    at org.spockframework.runtime.BaseSpecRunner.runFeature(BaseSpecRunner.java:238)
    at org.spockframework.runtime.BaseSpecRunner.runFeatures(BaseSpecRunner.java:188)
    at org.spockframework.runtime.BaseSpecRunner.doRunSpec(BaseSpecRunner.java:98)
    at org.spockframework.runtime.BaseSpecRunner.invoke(BaseSpecRunner.java:84)
    at org.spockframework.runtime.extension.MethodInvocation.proceed(MethodInvocation.java:88)
    at org.spockframework.runtime.extension.builtin.AbstractRuleInterceptor.evaluate(AbstractRuleInterceptor.java:37)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite$PojoCachedMethodSiteNoUnwrapNoCoerce.invoke(PojoMetaMethodSite.java:233)
    at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite.call(PojoMetaMethodSite.java:56)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:117)
    at grails.test.runtime.TestRuntimeJunitAdapter.evaluate(TestRuntimeJunitAdapter.groovy:73)
    at org.spockframework.runtime.extension.builtin.ClassRuleInterceptor.intercept(ClassRuleInterceptor.java:38)
    at org.spockframework.runtime.extension.MethodInvocation.proceed(MethodInvocation.java:87)
    at org.spockframework.runtime.BaseSpecRunner.invoke(BaseSpecRunner.java:471)
    at org.spockframework.runtime.BaseSpecRunner.runSpec(BaseSpecRunner.java:76)
    at org.spockframework.runtime.BaseSpecRunner.run(BaseSpecRunner.java:67)
    at org.spockframework.runtime.Sputnik.run(Sputnik.java:63)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
    at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)

我需要为此做测试:

def getDocumentoInfo(CrDocumento documento) {
  try {
     def vbr = ViewBoletoRegistro.findById(documento?.id)
     def crTaxa = CrTaxa.findByCrDocumento(documento)
  if (crTaxa) {
           return getTaxa(crTaxa, documento, vbr)
  }

   } catch (Exception ex) {
       log.error("Erro ao gerar documentoInfo: " +       ExceptionUtils.getFullStackTrace(ex))
       return [:]
 }
}


def getTaxa(CrTaxa crTaxa, documento, ViewBoletoRegistro vbr) {
    def vencimento = (crTaxa.dataVencimento <= new Date()) ? calculaDiasUteis(new Date(), 0) : crTaxa?.dataVencimento
    def tipoCursoId = crTaxa?.solicitacaoServico?.matricula?.ofertaPoloTurma?.ofertaPolo?.oferta?.modulo?.matriz?.curso?.tipoCurso?.id

    def desconto = crTaxa.valorDesconto == null ? 0 : crTaxa.valorDesconto
    def juros = 0
    if (((tipoCursoId == '03' || tipoCursoId == '14' || tipoCursoId == '20' && crTaxa.numeroParcela != '01') || tipoCursoId == '23') && crTaxa.dataVencimento <= new Date() && !crTaxa.dataPrimeiroRecebimento) {
        juros = calculaMultaNodia(documento.id, vencimento)
    } else {
        juros = crTaxa.valorJuros == null ? 0 : crTaxa.valorJuros
    }

    def maxParcelaCartao = ServicoPrecoItem.findByServico(crTaxa.solicitacaoServico.servico).parcelas

    def documentoInfo = [:]
    documentoInfo.id = documento.id
    documentoInfo.pessoa = crTaxa?.solicitacaoServico?.matricula?.aluno?.pessoa
    documentoInfo.nome = crTaxa?.solicitacaoServico?.matricula?.aluno?.nome + (crTaxa?.solicitacaoServico?.matricula ? " (${crTaxa?.solicitacaoServico?.matricula?.id})" : "")
    documentoInfo.email = crTaxa?.solicitacaoServico?.matricula?.aluno?.email
    documentoInfo.descricao = "Taxa"
    documentoInfo.valor = toBigDecimal(crTaxa.valor).add(toBigDecimal(juros))
    documentoInfo.valorTitulo = vbr?.valorNominalTitulo
    documentoInfo.data = vencimento
    documentoInfo.situacao = crTaxa.situacaoFaturamento.id
    documentoInfo.boleto = true
    documentoInfo.cartao = (maxParcelaCartao >= 1 ? true : crTaxa.numeroParcela == '01' ? true : false) && Colaborar.getBoolean('pagamento.cielo.parcela.enabled', true)
    documentoInfo.minParcelas = 1
    documentoInfo.maxParcelas = maxParcelaCartao >= 1 ? maxParcelaCartao : tipoCursoId == '14' ? 1 : tipoCursoId == '20' ? 1 : 3
    documentoInfo.conta = crTaxa.conta
    documentoInfo.apenasCartao = crTaxa.solicitacaoServico.cartao
    documentoInfo
}    

我的测试:

void 'teste taxa'(){
    setup:
    GroovySpy(CrTaxa, global:true)
    GroovySpy(ViewBoletoRegistro, global:true)

    when:
    def documento=CrDocumento.findOrSaveById(123)
    def documentoInfo=service.getDocumentoInfo(documento)

    then:
    1 *  ViewBoletoRegistro.findById("123")
    1 *  CrTaxa.findByCrDocumento(CrDocumento.findOrSaveById(123))
    documentoInfo.descricao=="Taxa"

}

对于 grails >= 3.3.0,您可以使用新的单元测试框架功能模拟域 类。实施 DataTestgetDomainClassesToMock():

class YourSpec extends Specification implements DataTest {

    Class[] getDomainClassesToMock() {
        [CrParcela, CrTaxa, ViewBoletoRegistro, CrDocumento]
    }

    // your tests ...

}

对于 grails < 3.3.0 你需要添加 Mock 注释:

@Mock([CrParcela, CrTaxa, ViewBoletoRegistro, CrDocumento])
class YourSpec extends Specification {
   // your tests ...
}