Groovy,如何模拟界面保持其他方法

时间:2014-05-23 22:29:23

标签: unit-testing grails testing groovy mocking

如何模拟实现接口的对象和不属于后者的方法?我需要aplicacaoPT来实现BindingProvider和buscaAplicacaoPorCodigo。演员工作,但buscaAplicacaoPorCodigo调用给出 MissingMethodException 。我尝试了一张地图和一张Expando:

import static org.junit.Assert.*
import grails.test.mixin.*
import grails.test.mixin.support.*
import org.junit.*
import javax.xml.ws.BindingProvider

@TestMixin(GrailsUnitTestMixin)
class CatalogClientServiceTests {

    void testFetch() {
        AplicacaoSoapService.metaClass.getAplicacaoSoapPort = { 
            [ getRequestContext: { new HashMap<String, Object>() }, 
            buscaAplicacaoPorCodigo: { String appCode -> "carrapato!" } ] as BindingProvider
        }

        def applicationDataFromCatalog = service.fetch("dino")
    }

    void testFetchFailsWithInvalidApplicationCode() {
        AplicacaoSoapService.metaClass.getAplicacaoSoapPort = { 
            def aplicacaoSoapPort = new Expando()
            aplicacaoSoapPort.getRequestContext = { new HashMap<String, Object>() }
            aplicacaoSoapPort.buscaAplicacaoPorCodigo = { String appCode -> "castanha!" }
            aplicacaoSoapPort as BindingProvider
        }

        shouldFail(IllegalArgumentException) { service.fetch("dino") }
    }

}

import javax.xml.ws.BindingProvider

class CatalogClientService {
    def aplicacaoPT = new AplicacaoSoapService().getAplicacaoSoapPort()
    def grailsApplication

    def fetch(String appCode) { 
        Map<String, Object> req_ctx = ((BindingProvider)aplicacaoPT).getRequestContext();
        req_ctx.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, grailsApplication.config.catalogAppEndPointAddress);

        def response = aplicacaoPT.buscaAplicacaoPorCodigo(appCode)
        println "response: $response"
    }

 }

我还尝试将buscaAplicacaoPorCodigo添加到BindingProvider的元类中,但它坚持使用其中一个实现进行所有测试。在下面的示例中,将打印响应(上图)&#34; castanha!&#34;或&#34; carrapato!&#34;在每次运行的两个测试中。

import static org.junit.Assert.*
import grails.test.mixin.*
import grails.test.mixin.support.*
import org.junit.*
import javax.xml.ws.BindingProvider

@TestMixin(GrailsUnitTestMixin)
class CatalogClientServiceTests {

    void testFetch() {
        BindingProvider.metaClass.buscaAplicacaoPorCodigo = { String appCode -> "carrapato!" }

        AplicacaoSoapService.metaClass.getAplicacaoSoapPort = { 
            [ getRequestContext: { new HashMap<String, Object>() } ] as BindingProvider
        }

        def applicationDataFromCatalog = service.fetch("dino")
    }

    void testFetchFailsWithInvalidApplicationCode() {
        BindingProvider.metaClass.buscaAplicacaoPorCodigo = { String appCode -> "castanha!" }

        AplicacaoSoapService.metaClass.getAplicacaoSoapPort = { 
            def aplicacaoSoapPort = new Expando()
            aplicacaoSoapPort.getRequestContext = { new HashMap<String, Object>() }
            aplicacaoSoapPort as BindingProvider
        }

        shouldFail(IllegalArgumentException) { service.fetch("dino") }
    }

}

为了简单起见,我删除了上面代码的一部分。

我希望有些人可以帮助我! :)

1 个答案:

答案 0 :(得分:2)

我对grails没有经验,但这似乎是与代理相关的问题。生成的代理没有buscaAplicacaoPorCodigo可用。

AFAIK,您有两种选择:使用Buscador创建一个接口buscaAplicacaoPorCodigo,然后创建一个super interface for both BindingProvider and Buscador,或者对于一个纯动态解决方案,metaClass生成代理的expando:

我嘲笑你的一些课程,希望我做对了。

BindingProvider.groovy:

interface BindingProvider {
    def getRequestContext()
}

其余的:

class AplicacaoSoapService {
    static BindingProvider getAplicacaoSoapPort() {
        assert false, "Nope, must be mocked"
    }
}

AplicacaoSoapService.metaClass.static.getAplicacaoSoapPort = {
    def e = new Expando(
        getRequestContext: { [:] }) as BindingProvider
    e.getMetaClass().buscaAplicacaoPorCodigo = { String a -> "amendoa!" }
    e
}

def provider = AplicacaoSoapService.aplicacaoSoapPort

assert provider.buscaAplicacaoPorCodigo("pudim") == "amendoa!"