2011-01-20 91 views
3

我想单元测试的一些代码,返回值看起来与此类似:如何模拟关闭以测试Grails服务结果?

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

我怎么能这样做? 谢谢!

回答

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 
2

像你一样的单元测试提出了真正的测试,只要数据库中给出正确的数据,就可以将它正确地组装到Item实例中。我会切换到集成测试,您可以访问真实的数据库,并使用db中的测试数据测试整个方法。

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