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

如何使用Mockery正确模拟clickhouse-go.driver.Row.Scan方法以填充参数值?

如何使用Mockery正确模拟clickhouse-go.driver.Row.Scan方法以填充参数值?

我明白你现在遇到的问题了——想通过Mockery模拟Scan方法,把值填充到传入的指针参数里,但直接给args[0]赋值根本没生效,对吧?这其实是Go里值传递的特性导致的,我来给你讲清楚怎么解决。

问题根源

你当前的代码里,args[0] = 1只是把切片中存储的指针副本替换成了整数1,并没有修改原来指针指向的内存区域。因为Go的函数参数是值传递,切片args里的每个元素都是传入参数的副本,所以直接修改args[0]不会影响到测试代码里的avg变量。

正确解决方案

正确的做法是先把args[0]转换成对应的指针类型,然后通过解引用修改它指向的内存值。下面是修改后的完整测试代码:

import "fmt"

func Test_1(test *testing.T) {
     test.Parallel()
    
     ch := ch_mock.NewMockConn(test)
     row := ch_mock.NewMockRow(test)
     row.EXPECT().Scan(mock.AnythingOfType("*int64")).RunAndReturn(func(args ...any) error {
        // 类型断言,确保第一个参数是*int64类型
        dest, ok := args[0].(*int64)
        if !ok {
            return fmt.Errorf("unexpected type for first argument: %T", args[0])
        }
        // 修改指针指向的实际内存值
        *dest = 1
        return nil
     })
    ch.EXPECT().QueryRow(mock.Anything, mock.Anything).Return(row)
    // 这里将ch注入到待测试的代码中...
}

这样当你的业务代码调用row.Scan(&avg)时,Mock里的代码会拿到&avg的指针副本,通过解引用*dest修改它指向的内存,avg自然就会被设置成1了。

扩展:处理多参数场景

如果需要同时填充多个不同类型的参数,比如int64和string,可以这样扩展代码:

row.EXPECT().Scan(mock.AnythingOfType("*int64"), mock.AnythingOfType("*string")).RunAndReturn(func(args ...any) error {
    // 处理第一个int64参数
    if destInt, ok := args[0].(*int64); ok {
        *destInt = 1
    } else {
        return fmt.Errorf("expected *int64 for first arg, got %T", args[0])
    }
    // 处理第二个string参数
    if destStr, ok := args[1].(*string); ok {
        *destStr = "test_result"
    } else {
        return fmt.Errorf("expected *string for second arg, got %T", args[1])
    }
    return nil
})

备注:内容来源于stack exchange,提问作者George

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.15 09:00:29