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

使用go-sqlmock模拟GORM时实际SQL与预期正则不匹配如何解决

问题原因
  • 符号不匹配:你预期SQL使用双引号"包裹表名、字段名,但GORM对接MySQL时生成的SQL默认使用反引号`作为标识符包裹符,二者不一致。
  • 占位符不匹配:你预期SQL使用PostgreSQL风格的$1作为参数占位符,但MySQL语法使用?作为参数占位符,二者不匹配。
  • 多余转义与符号:你使用了regexp.QuoteMeta对预期SQL做了全转义,且预期SQL的WHERE条件多了多余的括号,同时你初始化sqlmock时指定了QueryMatcherEqual完全匹配模式,多重差异导致匹配失败。
  • 可选注意点:你测试代码中构造返回行的列名写的是fast_name,但GORM默认会将结构体的LastName字段映射为蛇形的last_name,如果你的实体字段没有显式指定gorm标签为fast_name,后续会出现字段赋值为空的问题。
解决方法

直接修改测试代码中预期SQL的写法,匹配实际生成的SQL即可,QueryMatcherEqual模式下不需要使用regexp.QuoteMeta转义:

func (s *Suite) Test_repository_Get() {
    var (
        id        = uint(1)
        userName = "user-name"
        lastName = "fast-name"
    )
    // 修正预期SQL,和实际生成的完全一致,去掉QuoteMeta
    s.mock.ExpectQuery("SELECT * FROM `users` WHERE id = ? ORDER BY `users`.`id` LIMIT 1").
        WithArgs(id).
        WillReturnRows(sqlmock.NewRows([]string{"id", "user_name", "last_name"}).
            AddRow(id, userName, lastName))
    res, err := s.repository.GetUserByID(id)
    require.Nil(s.T(), err)
    require.Nil(s.T(), deep.Equal(&domain.User{ID: id, UserName: userName, LastName: lastName}, res))
}

如果不想严格匹配引号、空格等细节,也可以将sqlmock初始化时的匹配模式改为默认的正则匹配模式,去掉sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual)参数即可,此时可以用正则模糊匹配SQL。

内容的提问来源于stack exchange,提问作者Md. Abu Farhad

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.10 13:30:03