如何使用 go-sql 模拟 gorm 插入 (postgres)
How to mock gorm insert with go-sql (postgres)
我正在使用 Gorm with the postgresql driver. I try to mock a database insert with go-sqlmock:
type Test struct {
FirstName string `json:"first_name"`
}
func (db *DB) CreateTest() (*Test, error) {
test := Test{"c"}
if result := db.Create(&test); result.Error != nil {
return nil, result.Error
}
return &test, nil
}
func TestCreateUser(t *testing.T) {
_, mock, _ := sqlmock.NewWithDSN("sqlmock_db_0")
mockedGorm, _ := gorm.Open("sqlmock", "sqlmock_db_0")
defer mockedGorm.Close()
myDB := &DB{mockedGorm}
mock.ExpectExec("INSERT INTO test").WithArgs("c").WillReturnResult(sqlmock.NewResult(1, 1))
myDB.Exec("INSERT INTO test(first_name) VALUES (?)", "c")
if _, err := myDB.CreateTest(); err != nil {
t.Errorf("error was not expected: %s", err)
}
if err := mock.ExpectationsWereMet(); err != nil {
t.Errorf("there were unfulfilled expectations: %s", err)
}
}
不幸的是,这给了我一个错误:
error was not expected: all expectations were already fulfilled, call to database transaction Begin was not expected
如何使用 gorm、postgresql 和 sql-mock 正确测试插入?
我的代码有几个问题:
1) 正如@flimzy 正确指出的那样,必须有一个 ExpectBegin()
(和 ExpectCommit()
)语句。如果打开显示 GORM 正在做什么的 GORM 调试器,这一点会变得更加明显。
2) ExpectExec("INSERT INTO test").WithArgs("c")
显然不匹配 myDB.Exec("INSERT INTO test(first_name) VALUES (?)", "c")
3) 必须对语句进行转义,因为 go-sqlmock 采用正则表达式,这里 Go 的 https://godoc.org/regexp#QuoteMeta 派上用场了。
工作代码:
mock.ExpectBegin()
mock.ExpectExec(regexp.QuoteMeta("INSERT INTO \"tests\" (\"first_name\") VALUES (?)")).WithArgs("c").WillReturnResult(sqlmock.NewResult(1, 1))
mock.ExpectCommit()
我正在使用 Gorm with the postgresql driver. I try to mock a database insert with go-sqlmock:
type Test struct {
FirstName string `json:"first_name"`
}
func (db *DB) CreateTest() (*Test, error) {
test := Test{"c"}
if result := db.Create(&test); result.Error != nil {
return nil, result.Error
}
return &test, nil
}
func TestCreateUser(t *testing.T) {
_, mock, _ := sqlmock.NewWithDSN("sqlmock_db_0")
mockedGorm, _ := gorm.Open("sqlmock", "sqlmock_db_0")
defer mockedGorm.Close()
myDB := &DB{mockedGorm}
mock.ExpectExec("INSERT INTO test").WithArgs("c").WillReturnResult(sqlmock.NewResult(1, 1))
myDB.Exec("INSERT INTO test(first_name) VALUES (?)", "c")
if _, err := myDB.CreateTest(); err != nil {
t.Errorf("error was not expected: %s", err)
}
if err := mock.ExpectationsWereMet(); err != nil {
t.Errorf("there were unfulfilled expectations: %s", err)
}
}
不幸的是,这给了我一个错误:
error was not expected: all expectations were already fulfilled, call to database transaction Begin was not expected
如何使用 gorm、postgresql 和 sql-mock 正确测试插入?
我的代码有几个问题:
1) 正如@flimzy 正确指出的那样,必须有一个 ExpectBegin()
(和 ExpectCommit()
)语句。如果打开显示 GORM 正在做什么的 GORM 调试器,这一点会变得更加明显。
2) ExpectExec("INSERT INTO test").WithArgs("c")
显然不匹配 myDB.Exec("INSERT INTO test(first_name) VALUES (?)", "c")
3) 必须对语句进行转义,因为 go-sqlmock 采用正则表达式,这里 Go 的 https://godoc.org/regexp#QuoteMeta 派上用场了。
工作代码:
mock.ExpectBegin()
mock.ExpectExec(regexp.QuoteMeta("INSERT INTO \"tests\" (\"first_name\") VALUES (?)")).WithArgs("c").WillReturnResult(sqlmock.NewResult(1, 1))
mock.ExpectCommit()