2017-08-21 37 views
0

我有一个Grails的服务,做了where这样的查询:单元测试GORM调用与闭合

List<Car> search(Long makeId = null) { 
    Car.where { 
     join("make") 
     if(makeId) { 
      make.id == makeId 
     } 
    }.findAll() 
} 

我试图单元测试与斯波克这样的:

def setup() { 
    GroovyMock(Car, global: true) 
} 

void "test search"() { 
    when: 
     service.search() 
    then: 
     1 * Car.where {} 
} 

但是,我似乎无法找到一种方法来测试闭包的内容。

我可以得到测试通过验证1 * Car.where(_)通过,但我怎么能在封闭的内容的断言,即认为join被称为并在需要时make.id约束只规定?

+1

我更倾向于将测试搜索方法来代替。 在规范中,您将设置只有在指定了makeId时才返回的数据。因此,通过两个'when/then'块,您可以测试是否按预期提供makeId。 – bassmartin

回答

0

您可以将闭包的委托设置为DetachedCriteria的模拟来对其进行断言。 DetachedCriteria是gorm构建查询的主要类。

实施例:

given: 'Mocking DetachedCriteria' 
DetachedCriteria detachedCriteriaMock = Mock(DetachedCriteria) 
and: 'Just to avoid nullPointerException when findAll() call happens on service' 
1 * detachedCriteriaMock.iterator() >> [].listIterator() 
when: 
service.search(1L) 
then: 
// Capture the argument 
1 * Car.where(_) >> { args -> 
    args[0].delegate = detachedCriteriaMock 
    args[0].call() 

    return detachedCriteriaMock 
} 

// Join is a method on detached criteria 
1 * detachedCriteriaMock.join('make') 
// Make is an association, so detachedCriteria uses the methodMissing to find the property. 
// In this case, we call the closure setting the delegate to the mock 
1 * detachedCriteriaMock.methodMissing('make', _) >> { args -> 
    // args[1] is the list of arguments. 
    // args[1][0] is the closure itself passed to detachedCriteria 
    args[1][0].delegate = detachedCriteriaMock 
    args[1][0].call() 
} 
// If id is passed, it must compare (eq method) with value 1 
1 * detachedCriteriaMock.eq('id', 1L) 
+0

这对于测试'join'调用非常有用,我可以用它来测试'make.id'约束吗? – Raibaz

+0

是的!但在这种情况下,您想要测试与'make'调用方法的交互。所以你必须使用模拟器!我对我的示例代码做了一些重构。希望能帮助到你。 – rafaelim

+0

它肯定有帮助,我得到你在这里做什么,但与你的代码我得到一个'MissingMethodException:没有方法的签名:groovy.util.Expando.make()适用于参数类型[_closure stuff] ...我错过了什么? – Raibaz