Spock: mocked class's method is not being matched

人盡茶涼 提交于 2019-12-11 04:48:01

问题


I was able to get a passing test for the dumbed down version of my code (thanks to cgrim! Spock: method not recognized as an invocation), but with the real code it won't work unless the getAssetIdBatch returns something that is non-null. I can't figure out why my interactions aren't being implemented. Below, you can see three attempts to get getAssetIdBatch to return the map1 sample.

Here's a dumbed down version of the code:

class VmExportTaskSplitter implements TaskSplitter<Export> {

    @Inject
    AssetServiceClient assetServiceClient

    @Override
    int splitAndSend(Export export) {

        Map batch = [:]
        Map tags = [:]

        if (true) {
            println('test')
            batch = assetServiceClient.getAssetIdBatch(export.containerUuid,
                    export.userUuid, (String) batch.scrollId, tags)
            print('batch: ')
            println(batch)
        }

        return 1

    }
}

And now the test:

class VmExportTaskSplitterSpecification extends Specification{
    def "tags should be parsed correctly"(){
        setup:
        Export export = new Export(containerUuid: "000", userUuid: "000", chunkSize: 10)
        FilterSet filterSet = new FilterSet()
        filterSet.tag = [:]
        filterSet.tag['tag.Location'] = 'Boston'
        filterSet.tag['tag.Color'] = 'red'
        Map<String, String> expectedTags = ['tag.Location':'Boston', 'tag.Color':'red']
        ObjectMapper mapper = new ObjectMapper()
        export.filters = mapper.writeValueAsString(filterSet)

        def assetServiceClient = Mock(AssetServiceClientImpl) {
            Map map1 = [assetIds:["1","2","3","4","5"],scrollId:null]
            getAssetIdBatch(_ as String,_ as String, null, _ as Map) >> map1
            getAssetIdBatch('000', '000', null, ['tag.Location':'Boston', 'tag.Color':'red']) >> map1
            getAssetIdBatch(_, _, _, _) >> map1
        }

        VmExportTaskSplitter splitter = new VmExportTaskSplitter()
        splitter.assetServiceClient = assetServiceClient

        when:
        splitter.splitAndSend(export)

        then:
        1 * assetServiceClient.getAssetIdBatch(_ as String, _ as String, _, _ as Map)
    }
}

When this is run it can be seen that batch is still being printed as null. What am I doing wrong with setting up the interactions?

Using logging directory: './logs'
Using log file prefix: ''
test
batch: null

回答1:


You –like so many before– ran into the one giant gotcha of Spock: the combination of Mocking and Stubbing and the fact that it has to happen in one line. Form the docs:

Mocking and stubbing of the same method call has to happen in the same interaction.

You stubbed assetServiceClient.getAssetIdBatch to return map1 in your given block and then you verified the mocked call in your then block. The latter one implicitly instructs the mock to return null instead of map1. Think

1 * assetServiceClient.getAssetIdBatch(_ as String, _ as String, _, _ as Map) // >> null

Change that line to

1 * assetServiceClient.getAssetIdBatch(_ as String, _ as String, _, _ as Map) >> map1

and define map1 in the method's scope and it will work as expected.

You probably want to remove the duplicate from the given block as well.

Don't worry about this being in the then block. Spock executes all mocking and stubbing before you enter the when block. Step through the code if you'd like to see it.



来源:https://stackoverflow.com/questions/53267791/spock-mocked-classs-method-is-not-being-matched

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!