如何模拟关闭以测试Grails服务结果?

时间:2011-01-20 01:18:14

标签: testing grails groovy mocking metaclass

我想单元测试一些与此类似的代码的返回值:

Groovy Service code to test:
    def findByThisAndThat(something) {
            : 
        def items = []
        sql.eachRow(query, criteriaList, {
            def item = new Item(name:it.NAME)
            items.add(item)
        })
        [items: items, whatever:whatevervalue]
    }

单元测试代码计划:

   void testFindByThisAndThatReturnsAMapContainingItems(){
       Sql.metaClass.eachRow = { String query, List criteria, Closure c ->

           // call closure to get passed in items list
           // add one new Item(name:"test item") to list
       }

       def result = service.findByThisAndThat("", "")

       assert result.items
       assertEquals('test item', result.items[0].name)
   }

我该怎么做? 谢谢!

2 个答案:

答案 0 :(得分:2)

单元测试就像你提议的那样,只是提供了来自数据库的正确数据的测试,你可以将它正确地组装到Item实例中。我将切换到集成测试,您可以访问真实数据库并使用数据库中的测试数据测试整个方法。

单元测试数据库访问通常更多地是对模拟代码的测试,而不是对代码的测试,所以它通常没用。

答案 1 :(得分:1)

像方法一样使用它来调用闭包。或者,您也可以使用Closure.call()。将it的值作为第一个参数传递。

Sql.metaClass.eachRow = { String query, List criteria, Closure c ->
    def mockItems = ["test item"]
    mockItems.each { item ->
        c(item)
        // c.call(item) works too
    }
}

请注意,在测试结束时不会重置Sql metaClass。我建议在测试后清除它:

Sql.metaClass = null