简体   繁体   English

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

[英]How can I mock a grails 4 service in a controller unit test

I don't understand how mocking works in Grails 4.0.我不明白在 Grails 4.0 中模拟是如何工作的。 I have this unit test that fails (it is just an illustration of the real test, the real test actually involves the controller):我有一个失败的单元测试(它只是真实测试的一个说明,真正的测试实际上涉及控制器):

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"]]
    }

with error有错误

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)

and stdout和标准输出

null

The interesting thing is that this works fine if I use a very simple test class instead of MySearchService .有趣的是,如果我使用一个非常简单的测试类而不是 MySearchService这可以正常工作 So I am assuming that it has to do something with the way Grails/Spring is setup.所以我假设它必须与 Grails/Spring 的设置方式有关。 This might also explain the lines:这也可以解释以下几行:

Unmatched invocations (ordered by similarity):

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

But how do I set it up otherwise?但是我该如何设置呢? I can't find this anywhere in the documentation.我在文档中的任何地方都找不到这个。 Thanks for any help!谢谢你的帮助!

Similar question (without answer): How to partially mock service in Grails integration test类似问题(无答案): 如何在 Grails 集成测试中部分模拟服务

The syntax for your mock is incorrect - here's a working example tested in Grails 4.0.1您的模拟的语法不正确 - 这是在 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']
    }

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

Note this is likely not in the Grails docs as there is nothing Grails specific about it - just Spock.请注意,这可能不在 Grails 文档中,因为没有任何特定于 Grails 的内容 - 只是 Spock。

here is already a workaround that is not great:这里已经有一个不太好的解决方法:

    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"]]
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM