如何在控制器单元测试中模拟Grails 4服务

时间:2019-11-25 11:11:02

标签: spring unit-testing grails groovy mocking

我不明白模拟在Grails 4.0中如何工作。 我有一个失败的单元测试(这只是真实测试的一个说明,真实测试实际上涉及控制器):

import com.myapp.MySearchService

class ApiControllerSpec extends Specification implements ControllerUnitTest<ApiController> {

    def setup() {
    }

    def cleanup() {
    }

    void "test listSources"() {
        given:
        def mock = Mock(MySearchService) {
            find(_) >> [["label": "abc", "description": "xsad"]]
        }

        when:
        System.out.println(mock.find(''))

        then:
        1 * mock.find(_) >> [["label": "abc", "description": "xsad"]]
    }

有错误

Too few invocations for:

1 * mock.find(_) >> [["label": "abc", "description": "xsad"]]   (0 invocations)

Unmatched invocations (ordered by similarity):

1 * mock.invokeMethod('find', [<java.lang.String@0 value= hash=0>])


    at org.spockframework.mock.runtime.InteractionScope.verifyInteractions(InteractionScope.java:93)
    at org.spockframework.mock.runtime.MockController.leaveScope(MockController.java:77)
    at toe.ApiControllerSpec.test listSources(ApiControllerSpec.groovy:29)

和标准输出

null

有趣的是,如果我使用一个非常简单的测试类而不是MySearchService ,则可以正常工作。因此,我假设它必须与Grails / Spring的设置方式有关。这也可能解释了以下几行:

Unmatched invocations (ordered by similarity):

1 * mock.invokeMethod('find', [<java.lang.String@0 value= hash=0>])

但是我该如何设置呢?我在文档的任何地方都找不到。感谢您的帮助!

类似问题(无答案): How to partially mock service in Grails integration test

2 个答案:

答案 0 :(得分:3)

模拟的语法不正确-这是在Grails 4.0.1中测试的工作示例

    void "test something"() {
        given:
        def mock = Mock(SearchService) {
            1 * find(_) >> ['foobar'] // note the interaction count is required when defining this way.
        }

        when:
        def result = mock.find('')

        then:
        result == ['foobar']
    }

请参阅-http://spockframework.org/spock/docs/1.0/interaction_based_testing.html-部分:Declaring Interactions at Mock Creation Time

请注意,Grails文档中可能没有此内容,因为没有任何Grails特定信息,只有Spock。

答案 1 :(得分:0)

这已经不是一个很好的解决方法:

    void "test listSources"() {
        given:
        def mock = Mock(MySearchService) {
            invokeMethod('find', _) >> [["label": "abc", "description": "xsad"]]
        }

        when:
        System.out.println(mock.find(''))

        then:
        1 * mock.invokeMethod('find', _) >> [["label": "abc", "description": "xsad"]]
    }