You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将带参数的Spock Mock行为委托给真实ConfigDO实例

如何让Spock Mock的Table类方法调用委托给真实ConfigDO实例

我有一个Table类,其getDataFromTable方法接收一个参数,底层会依次委托给TableConfig::getTableData和ConfigDO::getTableMap。现在需要实现:当Mock Table(或其依赖的TableConfig)时,让带参数的getDataFromTable调用最终委托给真实的ConfigDO实例,即期望效果为:

getDataFromTable(argument) >> configDo.getTableDataMap().get(argument)

涉及类代码

Table类

package com.place.core;

import org.springframework.stereotype.Component;
import com.place.configuration.TableConfig;

@Component
public class Table {
    private final TableConfig tableConfig;
    
    public Table(TableConfig config) {
        this.tableConfig = config;
    }

    public String getDataFromTable(String tableName) {
        return tableConfig.getTableData(tableName);
    }
}

TableConfig类

package com.place.configuration;

import com.place.representation.ConfigDO;
import org.springframework.context.annotation.Configuration;

@Configuration
public class TableConfig {
    private final ConfigDO configDo;

    public TableConfig(ConfigDO config) {
        this.configDo = config;
    }

    public String getTableData(String tableName) {
        return configDo.getTableMap().get(tableName);
    }
}

ConfigDO类

package com.place.representation;

import lombok.Data;
import java.util.Map;

@Data
public class ConfigDO {
    private final Map<String, String> tableDataMap;
}

当前测试代码雏形:

class TableTest extends Specification {
    def configDo = new ConfigDO()

    def mockTableConfig = Mock(TableConfig) {
        // 想要实现:将TableConfig::getTableData的参数传递给Map::get调用
        getTableData(argument) >> configDo.getTableDataMap().get(argument)
    }
}

解决方案

在Spock中,可以通过参数捕获闭包实现将Mock方法的参数传递给真实实例的调用,以下是两种常用实现方式:

方式1:Mock TableConfig并转发参数

修改TableConfig的Mock定义,用闭包接收调用参数,再转发给真实ConfigDO的逻辑:

class TableTest extends Specification {
    // 初始化带测试数据的ConfigDO实例
    def testTableData = ["user": "user_table", "order": "order_table"]
    def configDo = new ConfigDO(tableDataMap: testTableData)

    def "测试getDataFromTable委托给真实ConfigDO"() {
        given:
        // Mock TableConfig,将getTableData的参数转发给configDo
        def mockTableConfig = Mock(TableConfig) {
            getTableData(_) >> { String tableName -> 
                configDo.getTableDataMap().get(tableName) 
            }
        }
        // 初始化真实Table类,注入Mock的TableConfig
        def table = new Table(mockTableConfig)

        expect:
        table.getDataFromTable("user") == "user_table"
        table.getDataFromTable("order") == "order_table"
        table.getDataFromTable("nonexist") == null
    }
}

方式2:直接Mock Table类并转发参数

如果需要直接Mock Table类,同样可以用闭包参数转发:

class TableTest extends Specification {
    def testTableData = ["user": "user_table", "order": "order_table"]
    def configDo = new ConfigDO(tableDataMap: testTableData)

    def "测试Mock Table类时委托给真实ConfigDO"() {
        given:
        def mockTable = Mock(Table) {
            getDataFromTable(_) >> { String tableName ->
                configDo.getTableDataMap().get(tableName)
            }
        }

        expect:
        mockTable.getDataFromTable("user") == "user_table"
    }
}

关键说明

  • _ 是Spock的参数匹配器,表示匹配任意参数;若需限制参数范围,可使用eq("user")等精确匹配器。
  • 闭包{ String tableName -> ... }会接收Mock方法被调用时传入的真实参数,随后即可用该参数调用ConfigDO的真实逻辑。
  • 需提前给ConfigDO的tableDataMap初始化测试数据,避免空指针异常。

内容的提问来源于stack exchange,提问作者spartanhooah

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 05:30:05