Groovy 1.8.6使用的metaClassed方法不正确

时间:2012-05-25 19:27:39

标签: grails groovy metaprogramming

我在使用Grails 2.0.1进行重构时偶然发现了这一点,但是我把这个问题的基础知识拉到了一个直接的常规1.8.6测试中,它仍然失败了。我遇到它是因为我的方法过去没有参数,我改变它采取1参数。当我更改实现生产代码时,我的测试都没有失败。这很奇怪,因为我在测试中使用的metaClass设置为不接受任何参数,但是当我传入参数时它仍然响应我的生产代码。所以在下面的例子中,我想知道为什么第二个metaClassing被调用而不是第一个。它不接受任何参数,因为你可以看到我正在传入一个。如果你切换metaClassing的顺序然后它适当地工作但在这种情况下顺序无关紧要,因为方法签名是不同的。任何有关为什么会发生这种情况的见解都将非常感激。

import groovy.util.GroovyTestCase

class FirstTest extends GroovyTestCase {

    void testStuff() {
        def object = new Object()
        object.metaClass.someMethodName = {Object obj ->
            "ONE"
        }
        object.metaClass.someMethodName = {
            "TWO"
        }

        def result = object.someMethodName(new Object())

        assert "ONE" == result //result is equal to "TWO" in this case
    }

}

修改

好像上面的代码可能比实用代码更令人困惑,所以这里是实际的代码。

原始生产代码:

def create() {
    render(view: "create", model: [domains: Domain.myCustomListMethod().sort{it.cn}])
}

原始测试代码:

@Test
void createShouldIncludeAListOfAllDomainsInModel() {
    def directory = GldapoDirectory.newInstance(
            "", [
                    url: "http://url.com",
                    userDn: "someUserName",
                    password: "superSecretPassword"
            ])
    controller.session.userDirectory = directory
    Domain.metaClass.'static'.myCustomListMethod = {
        [[cn:"1"], [cn:"2"]]
    }

    controller.create()

    assert [[cn:"1"], [cn:"2"]] == controller.modelAndView.model.domains
}

然后我更新了生产代码以传递session.userDirectory,我的测试仍未经修改,即使它没有设置为接收任何参数:

def create() {
    render(view: "create", model: [domains: Domain.list(session.userDirectory).sort{it.cn}])
}

1 个答案:

答案 0 :(得分:1)

默认情况下,闭包采用一个参数(类Object),即使没有声明(可通过默认变量it访问)

所以你的第二个关闭覆盖了第一个