控制器测试中的Grails 4.0模拟服务方法

时间:2019-12-09 04:04:35

标签: unit-testing grails spock grails-4

我有一个像这样的控制器:

class NotificationApiController {

    def countService

    def getCount() {
        def results = countService.getCount()

        render results as JSON
    }
}

控制器进行如下测试:

Closure doWithSpring() {{ ->
        countService(CountService)
    }}

CountService countService

def setup() {
}

def cleanup() {
}

void "test getCount method"() {
        given:
        def countService = Mock(CountService) {
            1 * getCount(_) >> [count: 2]
        }
        when:
        def y = controller.getCount()

        then:
        y == [count: 2]
    }

看来它总是调用Closure doWithSpring()中注入的实际CountService,而不是我的模拟countService,但是如果没有Closure doWithSpring()的定义,我会得到此错误

Cannot invoke method getCount() on null object
java.lang.NullPointerException: Cannot invoke method getCount() on null object

关于4.0中的单元测试的文档确实非常有限,我不确定该怎么做。我在Grails 2.3或3.3中看到了一些示例。版本,但它们似乎都不适合我,主要是因为我猜想Spock和Mixin框架的不同。有关如何执行此操作的任何建议?

1 个答案:

答案 0 :(得分:1)

您省略了一些可能会影响建议的细节,但是https://github.com/jeffbrown/chrisjiunittest上的项目显示了解决此问题的一种方法。

https://github.com/jeffbrown/chrisjiunittest/blob/a59a58e3b6ed6b47e1a8104f3e4d3bdb138abacc/src/test/groovy/chrisjiunittest/NotificationApiControllerSpec.groovy

package chrisjiunittest

import grails.testing.web.controllers.ControllerUnitTest
import spock.lang.Specification

class NotificationApiControllerSpec extends Specification implements ControllerUnitTest<NotificationApiController> {

    void "test something"() {
        setup:
        // whether or not this is the right thing to do
        // depends on some other factors, but this is
        // an example of one approach...
        controller.countService = Mock(CountService) {
            getCount() >> [count: 2]
        }

        when:
        controller.getCount()

        then:
        response.json == [count: 2]
    }
}

另一个选择:

package chrisjiunittest

import grails.testing.web.controllers.ControllerUnitTest
import spock.lang.Specification

class NotificationApiControllerSpec extends Specification implements ControllerUnitTest<NotificationApiController> {

    Closure doWithSpring() {
        // whether or not this is the right thing to do
        // depends on some other factors, but this is
        // an example of one approach...
        { ->
            countService MockCountService
        }
    }

    void "test something"() {
        when:
        controller.getCount()

        then:
        response.json == [count: 2]
    }
}

class MockCountService {
    Map getCount() {
        [count: 2]
    }
}