groovy - 如何让多个 MockFor 在 Groovy 中工作?

标签 groovy junit mocking

我正在尝试让多个模拟在 groovy 中工作。我设法让这个工作的唯一方法是创建我自己的模拟 - 添加一个元方法。

我尝试过使用嵌套使用语句,还尝试了一种使用和一种带有验证的代理,但这两种方法都不起作用。这两个都返回了失败 - “junit.framework.AssertionFailedError:此时不再需要调用‘pop’。需求结束。”

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}"
    }
}

编辑:重新评论模拟从方法构造和返回的东西,这就是我的做法......
@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应该是一个 stub ,因为您只使用它来注入(inject) bubbleProxy你可以对它进行验证。像这样,

    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 )。我能想到的最小的例子就是
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 的多个模拟闭包有效,看看这个人为的例子
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 在 Groovy 中工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32237956/

相关文章:

groovy - 在 Groovy 中打印闭包定义/源

Kotlin:IllegalAccessException:类 BlockJUnit4ClassRunner 无法使用修饰符 “private” 访问类 Foo 的成员

java - 如何在 JUnit 测试中强制命中二级缓存?

java - Selenium JUnit 4 测试 - findElement() 的用法

testing - rspec 模拟外部 api

groovy - Groovy findAll 闭包中的复杂过滤逻辑

groovy - 使用 StreamingMarkupBuilder 在标签内生成 CDATA

java - 测试类中没有可以由可用注入(inject)满足的构造函数

grails - Grails Blob为pdf

c# - 最小起订量的链接方法