2017-08-21 71 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