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

SQLMock结合Gorm模拟Postgres插入报查询不预期错误的解决方法

SQLMock结合Gorm测试Postgres插入操作的正确配置

触发报错的核心原因

你的测试连续匹配失败,本质是三个代码层面的错误,和regexp.QuoteMeta的转义效果无关:

  • 预期类型用错:Gorm默认的Create插入操作是写操作,底层调用Exec接口,你错用了ExpectQuery去匹配需要返回结果集的查询类操作,调用类型完全不匹配。
  • 匹配字符串拼错:你把SQL语句+参数调试日志的完整输出(即SQL xxx with args [xxx]的日志格式)当成了要匹配的SQL本身,实际执行时传给数据库的SQL根本不包含后面的args日志段,自然匹配不上。
  • 参数匹配方式错:你把args的结构体打印内容塞给regexp.QuoteMeta做正则匹配,这部分内容是SQLMock内部的调试日志格式,不是真正传给驱动的参数值,硬拼永远无法对齐。

正确的配置步骤

  • 替换预期方法:用ExpectExec替代原来的ExpectQuery,匹配无结果集的写操作。
  • 提取纯SQL做正则转义:只把核心插入语句传给regexp.QuoteMeta,删掉后面拼接的args日志文本。
  • 用链式方法做参数匹配:通过WithArgs按顺序声明所有传入的参数值,让SQLMock自动完成参数校验,不用手动匹配日志格式的结构体。
  • 补全预期返回值:给Exec预期设置WillReturnResult返回插入影响行数,否则SQLMock会判定预期未完成。
  • 匹配事务语句:如果Gorm没开启SkipDefaultTransaction配置,需要在测试预期里先匹配BEGIN,最后匹配COMMIT,否则会因为事务调用未预期报错。

修正后的测试代码示例

// 纯SQL语句,不含日志拼接内容
expectedInsertSQL := `INSERT INTO "users" ("id","name","surname","birthdate","company","custom_claims","deleted") VALUES ($1,$2,$3,$4,$5,$6,$7)`

// 匹配Gorm默认开启的事务(如果开启了SkipDefaultTransaction可删掉这两行)
suite.mock.ExpectBegin()
suite.mock.ExpectExec(regexp.QuoteMeta(expectedInsertSQL)).
    // 按参数顺序声明匹配值
    WithArgs(
        ID,      // 对应$1的用户ID
        nil,     // 对应$2的name空指针
        nil,     // 对应$3的surname空指针
        nil,     // 对应$4的birthdate空指针
        nil,     // 对应$5的company空指针
        nil,     // 对应$6的custom_claims空指针
        nil,     // 对应$7的deleted空值
    ).
    // 返回插入操作的影响行数,供Gorm解析
    WillReturnResult(sqlmock.NewResult(1, 1))
suite.mock.ExpectCommit()

// 执行被测逻辑
user, err2 := postgres.CreateUser(users.User{
    ID: ID,
})

常见调试注意事项

  • 不要把SQLMock打印的错误日志原文直接当匹配字符串:日志是面向人读的格式化输出,不是实际驱动执行的原始SQL/参数内容。
  • 如果不需要严格校验参数值,可以省略WithArgs链式调用,SQLMock会自动接受任意传入的参数,降低测试对参数格式的耦合。
  • 注意:默认Gorm的Create是Exec类型,只有配置了插入后通过Returning子句返回全量字段时,才会走Query类调用,此时需要替换回ExpectQuery,并配置对应字段的返回结果集。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.23 15:06:03