如何在Groovy中使用多个MockFor? [英] How do I get multiple MockFor working in Groovy?

查看:87
本文介绍了如何在Groovy中使用多个MockFor?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试让多种模拟在Groovy中工作.我设法做到这一点的唯一方法是创建自己的模拟程序-添加元方法.

I am trying to get multiple mocks working in groovy. The only way I have managed to get this working is to create my own kind of mock - adding a meta method.

我尝试使用嵌套的use语句,还尝试了一种用法和一个带有verify的代理,但两者均无效.两者都返回失败-"junit.framework.AssertionFailedError:此时不再需要对'pop'的调用.需求结束."

I have tried using nested use statements and also tried one use and one proxy with verify, neither of which worked. Both of these returned a failure - "junit.framework.AssertionFailedError: No more calls to 'pop' expected at this point. End of demands."

import groovy.mock.interceptor.MockFor
import org.junit.Test

class MockTest {
    // results in No more calls to 'pop' expected at this point. End of demands.
    @Test
    public void testMock() {
        MockFor pupilMock = new MockFor(Pupil)
        MockFor bubbleMock = new MockFor(SomeService)
        GroovyObject bubbleProxy = bubbleMock.proxyInstance()
        pupilMock.demand.blowBubble { String colour ->
            return bubbleProxy
        }
        bubbleMock.demand.pop {}
        pupilMock.use {
            bubbleMock.use {
                Teacher teacher = new Teacher()
                teacher.lesson("red")
            }
        }
    }
    // results in No more calls to 'pop' expected at this point. End of demands.
    @Test
    public void testProxy() {
        MockFor pupilMock = new MockFor(Pupil)
        MockFor bubbleMock = new MockFor(SomeService)
        GroovyObject bubbleProxy = bubbleMock.proxyInstance()
        pupilMock.demand.blowBubble { String colour ->
            return bubbleProxy
        }
        bubbleMock.demand.pop {}
        pupilMock.use {
                Teacher teacher = new Teacher()
                teacher.lesson("red")
        }
        bubbleMock.verify(bubbleProxy)
    }
    // only using a single mock so works
    @Test
    public void testMetaclass() {
        MockFor pupilMock = new MockFor(Pupil)
        SomeService.metaClass.pop = { println "pop was called" }
        SomeService metaBubble = new SomeService("red")
        pupilMock.demand.blowBubble { String colour ->
            return metaBubble
        }
        pupilMock.use {
                Teacher teacher = new Teacher()
                teacher.lesson("red")
        }
    }
}

class Teacher {
    public void lesson(String colour) {
        Pupil pupil = new Pupil()
        SomeService bubble = pupil.blowBubble(colour)
        bubble.pop()
    }
}

class Pupil {
    SomeService blowBubble(String colour) {
        SomeService child = new SomeService(colour)
        return child
    }
}

class SomeService {
    String colour

    SomeService(String colour) {
        this.colour = colour
    }
    void pop() {
        println "popped ${colour}"
    }
}

重新评论模拟从方法构造和返回的东西,这就是我的方法...

Re comment about mocking something constructed and returned from a method, this is how I do it...

@Test
public void testMockReturned() {
    MockFor bubbleMock = new MockFor(SomeService)
    bubbleMock.demand.pop {}
    bubbleMock.use {
        Pupil pupil = new Pupil()
        SomeService service = pupil.blowBubble("red")
        service.pop()
    }
}

推荐答案

在这种情况下,Pupil应该是一个存根,因为您仅使用它来注入bubbleProxy以便可以对其进行验证.像这样

In this case, Pupil should be a stub since you're only using it to inject bubbleProxy to you can perform verification against it. Like this,

    import groovy.mock.interceptor.*
    import org.junit.Test

    class MockTest {
        @Test
        public void testMock() {
            StubFor pupilMock = new StubFor(Pupil)
            MockFor bubbleMock = new MockFor(SomeService)
            GroovyObject bubbleProxy = bubbleMock.proxyInstance()
            pupilMock.demand.blowBubble { String colour ->
                return bubbleProxy
            }
            bubbleMock.demand.pop {}
            bubbleMock.use {
                Teacher teacher = new Teacher()
                teacher.lesson("red")
            }
        }
    }

此外,我相信调用proxyInstance()时,需求会复制到代理上,因此您需要在实例化代理之前对需求进行配置. 但是,我不认为多个模拟存在问题,我认为您不能将实例模拟和类模拟混合在一起(您正在使用SomeService进行此操作).我能想到的最小的例子证明了这一点

Also, I believe the demands are copied onto the proxy when proxyInstance() is called, so you need to have your demands configured before instantiating the proxy. However, I don't think there's a problem with multiple mocks, I think you just can't mix instance and class mocks (which you are doing with SomeService). The smallest example I could think of that demonstrates this was

import groovy.mock.interceptor.MockFor

// this works
missyMock = new MockFor(Missy)
missyMock.demand.saySomethingNice {}
missy = missyMock.proxyInstance()
missy.saySomethingNice()
missyMock.verify(missy)

// as does this
missyMock = new MockFor(Missy)
missyMock.demand.saySomethingNice {}
missyMock.use {
    new Missy().saySomethingNice()
}

// this don't
missyMock = new MockFor(Missy)
missyMock.demand.saySomethingNice {}
missy = missyMock.proxyInstance()
missyMock.use {  // fails here in use()'s built-in verify()
    missy.saySomethingNice()
}
missyMock.verify(missy)

class Missy {
    void saySomethingNice() {}
}

为演示带有嵌套use闭包的多重模拟的工作原理,请查看此人为设计的示例

To demonstrate that the multiple mocks with nested use closures works, look at this contrived example

import groovy.mock.interceptor.MockFor
import org.junit.Test

class MockTest {
    @Test
    public void testMock() {
        MockFor lessonMock = new MockFor(Lesson)
        MockFor pupilMock = new MockFor(Pupil)
        lessonMock.demand.getLessonPlan {}
        pupilMock.demand.getName {}

        pupilMock.use {
            lessonMock.use {
                Teacher teacher = new Teacher()
                Pupil pupil = new Pupil()
                Lesson lesson = new Lesson()
                teacher.teach(pupil, lesson)
            }
        }
    }
}

class Teacher {
    void teach(Pupil pupil, Lesson lesson) {
        println "Taught ${pupil.getName()} $lesson by ${lesson.getLessonPlan()}"
    }
}

class Pupil {
    String name
}

class Lesson {
    LessonPlan lessonPlan

    static class LessonPlan {}
}

这篇关于如何在Groovy中使用多个MockFor?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆