如何模拟'新'运算符

时间:2012-05-14 18:52:07

标签: testing grails groovy constructor mocking

我正在测试一些使用java库的groovy代码,我想模拟库调用,因为他们使用网络。因此,测试中的代码类似于:

def verifyInformation(String information) {
    def request = new OusideLibraryRequest().compose(information)
    new OutsideLibraryClient().verify(request)
}

我尝试使用MockFor和StubFor,但我收到错误,例如:

No signature of method: com.myproject.OutsideLibraryTests.MockFor() is applicable for argument types: (java.lang.Class) values: [class com.otherCompany.OusideLibraryRequest]  

我正在使用Grails 2.0.3。

2 个答案:

答案 0 :(得分:9)

我刚刚发现我们总是可以通过MetaClass覆盖构造函数,因为Grails 2将在每次测试结束时重置MetaClass修改。

这个技巧比Groovy的MockFor更好。例如,AFAIK,Groovy的MockFor不允许我们模拟JDK的类java.io.File。但是,在下面的示例中,您不能使用File file = new File("aaa"),因为实际对象类型是Map,而不是File。这个例子是Spock规范。

def "test mock"() {
    setup:
    def fileControl = mockFor(File)
    File.metaClass.constructor = { String name -> [name: name] }
    def file = new File("aaaa")

    expect:
    file.name == "aaaa"
}

答案 1 :(得分:6)

MockFor's constructor的第二个可选参数是interceptConstruction。如果将此属性设置为true,则可以模拟构造函数。例如:

import groovy.mock.interceptor.MockFor
class SomeClass {
    def prop
    SomeClass() {
        prop = "real"
    }
}

def mock = new MockFor(SomeClass, true)
mock.demand.with {
    SomeClass() { new Expando([prop: "fake"]) }
}
mock.use {
    def mockedSomeClass = new SomeClass()
    assert mockedSomeClass.prop == "fake"
}

但是,请注意,您只能模拟像这样的groovy对象。如果您遇到Java库,可以将Java对象的构造转换为工厂方法并模拟它。