grails集成测试中的模拟方法继续进行其他测试

Des*_*tor 2 grails integration-testing mocking

我有一个集成测试,我有时想要模拟服务方法的返回.但是,我已经看到,一旦我模拟了该方法,调用它的后续测试也将使用模拟函数.

这是正常的吗?如果是这样,我怎样才能进行有时使用模拟函数的测试,有时候会使用真正的实现?

这是我的代码:

MyController {
    def someService

    def save(){
        ...
        def val = someService.methodToMock()//sometimes want to mock other times, not
        ...
    }
}

MyTest {

    def "test 1"(){
        ...
        //I want to mock here
        myController.someService.metaClass.methodToMock = { [] }
        ...
        myController.save()
    }

    def "test 2"(){
        ...
        //I don't want to mock here, however 
        // it is returning the mocked results
        myController.save()
    }
}
Run Code Online (Sandbox Code Playgroud)

Bur*_*ith 5

通常,您不希望在集成或功能测试中更改与元类相关的任何内容,仅在单元测试中.预计您将在单元测试中执行此操作,并且每次测试后或每个测试类运行后都会自动支持还原原始元类,具体取决于Grails的版本以及配置方式.但在集成测试中并非如此.

您可以使用几种不同的方法.如果您使用无类型依赖注入,例如def someService,那么您可以用您想要的任何内容覆盖实际服务实例,并且只要它具有您将在测试方法期间调用的方法,控制器将不知道或关心这不是真正的服务.

在这种情况下,我喜欢使用闭包映射,因为Groovy将调用闭包,就像它是一个方法一样.所以对于'test 1'你可以这样做:

def "test 1"() {
    ...
    def mockedService = [methodToMock: { args -> return ... }]
    myController.someService = mockedService
    ...
    myController.save()
}
Run Code Online (Sandbox Code Playgroud)

这是有效的,因为您为每个测试获得了一个新的控制器实例,并且您只为该实例更改了服务,但实际服务根本不受影响.

您的控制器someService.methodToMock()实际调用,someService.get('methodToMock').call()但是地图访问和闭包调用语法可以利用Groovy的语法糖看起来像常规方法调用.

另一种选择是子服务服务并覆盖您想要的方法,并用它替换注入的实例.如果键入依赖注入(例如SomeService someService),则必须使用此类似的东西.创建一个命名子类(class TestSomeService extends SomeService { ... })或创建一个匿名内部类:

def "test 1"() {
    ...
    def mockedService = new SomeService() {
        def methodToMock(args) {
            return ...
        }
    }
    myController.someService = mockedService
    ...
    myController.save()
}
Run Code Online (Sandbox Code Playgroud)