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

使用DATA-DOG/sqlmock测试GORM接口时出现ExpectedBegin报错如何解决

问题产生原因
  • 预期执行顺序和GORM实际执行逻辑不匹配:GORM默认仅对Save/Update等写操作自动开启事务,First类读操作不会触发事务。你当前的预期顺序在用户更新提交事务后,先预期了Begin操作,但实际业务代码下一步执行的是user_profiles表的读查询,不会触发事务开启,sqlmock收到查询请求时和下一个预期的Begin不匹配,直接报错。
  • SQL匹配规则错误:你使用regexp.QuoteMeta全匹配查询语句,但GORM生成的user_profiles查询语句末尾会自动拼接ORDER BY "user_profiles"."id" LIMIT 1后缀,全匹配会导致匹配失败。
  • 预期配置不全:你漏了user_profiles保存操作对应的事务、执行语句、提交的预期配置。
解决方案

1. 调整预期执行顺序

按照业务代码实际执行流配置预期,正确顺序如下:

  1. 匹配users表查询请求(读操作,无事务)
  2. 匹配用户保存的事务开启、执行更新、事务提交
  3. 匹配user_profiles表查询请求(读操作,无事务)
  4. 匹配用户配置保存的事务开启、执行更新、事务提交

2. 修正SQL匹配规则

不用全量匹配SQL,改用前缀匹配规避GORM自动生成的后缀带来的匹配问题。

3. 补全所有操作的预期配置

修正后的测试mock部分代码参考:

// 1. 预期查询用户
mock.ExpectQuery(regexp.MustCompile(`SELECT * FROM "users" WHERE email = \$1`)).
    WithArgs("email").
    WillReturnRows(rows)
// 2. 预期保存用户的事务流程
mock.ExpectBegin()
mock.ExpectExec(regexp.MustCompile(`UPDATE "users"`)).
    WillReturnResult(sqlmock.NewResult(1, 1))
mock.ExpectCommit()
// 3. 预期查询用户配置(无事务,直接匹配查询)
mock.ExpectQuery(regexp.MustCompile(`SELECT * FROM "user_profiles" WHERE email = \$1 AND provider = \$2 AND external_user_id = \$3`)).
    WithArgs("email", "provider", "testID").
    WillReturnRows(profileRows)
// 4. 预期保存用户配置的事务流程
mock.ExpectBegin()
mock.ExpectExec(regexp.MustCompile(`UPDATE "user_profiles"`)).
    WillReturnResult(sqlmock.NewResult(1, 1))
mock.ExpectCommit()

// 测试逻辑执行完后追加预期校验,排查遗漏的预期
if err := mock.ExpectationsWereMet(); err != nil {
    t.Errorf("未满足所有mock预期: %s", err)
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 22:27:03