使用Gorm与Sqlmock测试Go Lambda函数时的报错问题排查
问题原因及修复方案
1. 错误使用ExpectQuery处理DELETE操作
DELETE属于数据库写操作,sqlmock中需用ExpectExec而非ExpectQuery——ExpectQuery仅适用于SELECT类查询语句,这是导致预期不匹配的核心原因之一。
2. 时间格式字符串错误
Go的时间格式化基于参考时间Mon Jan 2 15:04:05 MST 2006,你写的"2006-02-01"实际对应年-日-月,这会导致月份被解析为日期数字,出现2022-13-06这种非法月份的错误。正确的年-月-日格式应为"2006-01-02"。
3. 表名与GORM默认生成规则不符
GORM默认将结构体名转为复数下划线格式:
Availability对应的默认表名是availabilities(而非你测试中写的availability)Reservation对应的默认表名是reservations(此部分正确)
若你的结构体未自定义表名,需修正测试中的表名匹配规则。
4. 直接拼接SQL字符串的风险
不要直接将时间字符串拼接到SQL中,应使用参数化匹配,避免测试运行时的时间差导致匹配失败。
修复后的测试代码
func TestDoCleanup(m *testing.T) { var mock sqlmock.Sqlmock var db *sql.DB var err error db, mock, err = sqlmock.New() assert.Nil(m, err) dialector := mysql.New(mysql.Config{ DSN: "sqlmock_db_0", DriverName: "mysql", Conn: db, SkipInitializeWithVersion: true, }) conn, err := gorm.Open(dialector, &gorm.Config{}) if err != nil { m.Errorf("Failed to open connection to DB: %v", err) } if conn == nil { m.Error("Failed to open connection to DB: conn is nil") } defer db.Close() sixMonthsAgo := time.Now().AddDate(0, -6, 0).Format("2006-01-02") // 用ExpectExec匹配DELETE操作,使用参数化校验 mock.ExpectExec("DELETE FROM availabilities WHERE date_to <= ?"). WithArgs(sixMonthsAgo). WillReturnResult(sqlmock.NewResult(0, 0)) mock.ExpectExec("DELETE FROM reservations WHERE date_to <= ?"). WithArgs(sixMonthsAgo). WillReturnResult(sqlmock.NewResult(0, 0)) DoCleanup(conn) err = mock.ExpectationsWereMet() assert.Nil(m, err) }
同步修正原函数的时间格式错误
原函数中的时间格式同样错误,需同步修改:
func DoCleanup(con *gorm.DB) { // 修正为正确的年-月-日格式 sixMonthsAgo := time.Now().AddDate(0, -6, 0).Format("2006-01-02") con.Where("date_to <= ?", sixMonthsAgo).Delete(&Availability{}) con.Where("date_to <= ?", sixMonthsAgo).Delete(&Reservation{}) }
内容的提问来源于stack exchange,提问作者Bird87 ZA
相关产品推荐
相关产品推荐

