unit-testing - 使用闭包对 GORM 调用进行单元测试

标签 unit-testing grails closures spock

我有一个执行 where 的 Grails 服务像这样查询:

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

我正在尝试使用 Spock 对它进行单元测试,如下所示:
def setup() {
    GroovyMock(Car, global: true)
}

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

但是,我似乎找不到测试闭包内容的方法。

我可以通过验证 1 * Car.where(_) 来通过测试,但是我怎样才能对闭包的内容做出断言,即 join被调用并且 make.id仅在需要时指定约束?

最佳答案

您可以将闭包的委托(delegate)设置为 DetachedCriteria 的 Mock 以对其进行断言。 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)

关于unit-testing - 使用闭包对 GORM 调用进行单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45802933/

相关文章:

PHP闭包范围问题

unit-testing - 如何覆盖出现在 TestNG 报告中的测试方法名称?

grails - Grails-从配置文件获取作业触发值

javascript - 是否可以在 JavaScript 中更改闭包内的变量?

mysql - Grails id 映射自动增量 - MySQL

grails - Grails Spring安全核心

ruby - 为什么 ruby​​ 方法没有词法作用域?

c# - 为什么 Moq 抛出 "expected Invocation on the mock at least once"。在哪里设置一次,即使它被设置为空?

c# - MSTest 相当于 NUnit 的参数化测试吗?

javascript - 使用 Jasmine 2.0 对 $scope.$evalAsync 函数进行单元测试