grails - 如何防止服务的元类被覆盖

标签 grails dependency-injection integration-testing spring-webflow expandometaclass

我试图在集成测试中模拟对外部服务的调用,该服务用于 grails webflow。该服务不在流或 session 范围内,而是通过依赖注入(inject)添加的,请参阅 here .

我已经设法找到一种方法来通过使用 ExpandoMetaClass 替换它的元类来覆盖服务。这些更改仅在单独运行测试时起作用,如果在此测试之前运行另一个使用相同服务的测试,则元类更改将消失。

覆盖元类的部分:

static {
    ExpandoMetaClass someService = new ExpandoMetaClass(Object, false)
    someService.invokeMethod = { String name, args ->
        def result = 'success'
        if(name.equals('accessAnotherSystem')
        {
            StackTraceUtils.sanitize(new Throwable()).stackTrace.each
            {
                if(it.methodName.equals('test_method_I_Want_failure_in')
                {
                    result = 'exception'
                }
            }
            return result
        }

        def validMethod = SomeService.metaClass.getMetaMethod(name, args)
        if (validMethod != null)
        {
            validMethod.invoke(delegate, args)
        }
        else
        {
            SomeService.metaClass.invokeMissingMethod(delegate, name, args)
        }
    }
    someService.initialize()
    SomeService.metaClass = someService
}

相关问题:How to change a class's metaClass per test

有没有办法保留我对测试的更改,或者有其他方法可以覆盖服务。

最佳答案

如果您想在每个测试方法的测试用例中覆盖服务,有一种更简单的方法。看一个例子:

class SomeControllerSpec extends Specification {

    def someService

    void "test any external method for success response"() {
        given: "Mocked service method"
        someService.metaClass.accessAnotherSystem = { arg1, arg2 ->
            return "some success response"
        }

        when: "Any controller method is called which calls this service method"
        // Your action which calls that service method

        then: "Result will processed coming from mocked method"
        // Your code
    }
}

您可以对任何服务测试方法执行相同的操作。如果您想模拟您正在为其编写测试用例的同一服务的方法,那么就来吧..
class SomeServiceSpec extends Specification {

    def someService

    void "test external method call"() {
        given: "Mocked service method"
        someService.metaClass.methodA = { arg1, arg2 ->
            return "some success response"
        }

        when: "A method is called which invokes the another method"
        // Your another service method which call the same method
        someService.methodB()    // Where methodB() invokes the methodA() internally in your code

        then: "Result will processed coming from mocked method"
        // Your code
    }
}

关于grails - 如何防止服务的元类被覆盖,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27623737/

相关文章:

grails - 在Grails Controller 中更新HasMany关系

dependency-injection - 谁创造了 "Inversion of Control Container"这个术语,哪个公共(public)容器最先出现?

c# - 从 MVC3 .Net 应用程序发送的集成测试电子邮件

c# - 使用 Mock HttpClient 进行 Mock Refit SDK 注入(inject)以进行集成测试

grails - 如何在 View 中将值从 View 传递到 Controller

grails - Grails GORM/HQL-从关联中检索数据

c# - 我应该如何使用 IoC/依赖注入(inject)来处理我的实体/域对象?

c++ - [Boost]::DI 从注入(inject)器创建唯一的 shared_ptr 对象

automation - 哪个更适合网络测试?录音播放自动化或编码?

grails - 在grails中保存域对象