我在模拟gorm INSERT查询时遇到了很多麻烦。我选择好的时候能够通过我的测试,但插入时我遇到了这个错误。
# gorms's debug output
INSERT INTO "groups" ("created_at","updated_at","deleted_at","name","description") VALUES ('2018-05-01 17:46:15','2018-05-01 17:46:15',NULL,'Group 1','A good group') RETURNING "groups"."id"
# Error returned from *gorm.DB.Create
2018/05/01 17:46:15 Error creating group: call to Query 'INSERT INTO "groups" ("created_at","updated_at","deleted_at","name","description") VALUES ($1,$2,$3,$4,$5) RETURNING "groups"."id"' with args [{Name: Ordinal:1 Value:2018-05-01 17:46:15.384319544 -0700 PDT m=+0.005382104} {Name: Ordinal:2 Value:2018-05-01 17:46:15.384319544 -0700 PDT m=+0.005382104} {Name: Ordinal:3 Value:<nil>} {Name: Ordinal:4 Value:Group 1} {Name: Ordinal:5 Value:A good group}], was not expected, next expectation is: ExpectedExec => expecting Exec or ExecContext which:
- matches sql: '^INSERT INTO "groups" (.+)$'
- is with arguments:
0 - {}
1 - {}
2 - <nil>
3 - Group 1
4 - A good group
- should return Result having:
LastInsertId: 1
RowsAffected: 1
我尝试了多个不同版本的正则表达式,甚至在regex101.com上使用golang测试了匹配,但我似乎无法让我的sqlmock与gorm的插入匹配。
这是我的测试:
type AnyTime struct{} // I don't actually know if I even need this
func (a AnyTime) Match(v driver.Value) bool {
_, ok := v.(time.Time)
return ok
}
func TestGroupService_Create(t *testing.T) {
db, mock, err := sqlmock.New()
if err != nil {
log.Fatalf("can't create sqlmock: %s", err)
}
models.DB, err = gorm.Open("postgres", db)
if err != nil {
log.Fatalf("can't open gorm connection: %s", err)
}
defer db.Close()
models.DB.LogMode(true)
name := "Group 1"
description := "A good group"
mock.ExpectExec("^INSERT INTO \"groups\" (.+)$").WithArgs(AnyTime{}, AnyTime{}, nil, name, description).WillReturnResult(sqlmock.NewResult(1, 1))
s := GroupService{}
req := &pb.CreateGroupRequest{
Name: name,
Description: description,
}
resp, err := s.Create(context.Background(), req)
assert.Nil(t, err)
if assert.NotNil(t, resp) {
assert.Equal(t, resp.Group.Name, name)
assert.Equal(t, resp.Group.Description, description)
}
err = mock.ExpectationsWereMet()
assert.Nil(t, err)
}
和我的服务方法我试图测试:
func (server *GroupService) Create(ctx context.Context, request *pb.CreateGroupRequest) (*pb.CreateGroupReply, error) {
var group models.Group
group.Name = request.Name
group.Description = request.Description
db := models.DB
if err := db.Create(&group).Error; err != nil {
log.Printf("Error creating group: %v", err)
return nil, err
}
createReply := pb.CreateGroupReply{
Group: mapGroupToService(group),
}
return &createReply, nil
}
我似乎无法解决这个问题。谢谢!
答案 0 :(得分:0)
我可以通过切换到go-mocket库来模拟和插入。它似乎是专门为GORM制作的。我很想知道为什么sqlmock插入不起作用,但这是我现在的解决方案:
func SetupTests() *gorm.DB {
mocket.Catcher.Register()
db, err := gorm.Open(mocket.DRIVER_NAME, "")
if err != nil {
log.Fatalf("error mocking gorm: %s", err)
}
// Log mode shows the query gorm uses, so we can replicate and mock it
db.LogMode(true)
models.DB = db
return db
}
func TestGroupService_Create(t *testing.T) {
db := SetupTests()
defer db.Close()
var mockedId int64 = 64
mocket.Catcher.Reset().NewMock().WithQuery("INSERT INTO \"groups\"").WithId(mockedId)
s := GroupService{}
name := "Group 1"
description := "A good group"
req := &pb.CreateGroupRequest{
Name: name,
Description: description,
}
resp, err := s.Create(context.Background(), req)
assert.Nil(t, err)
if assert.NotNil(t, resp) {
assert.Equal(t, uint32(mockedId), resp.Group.Id)
assert.Equal(t, name, resp.Group.Name)
assert.Equal(t, description, resp.Group.Description)
}
}
答案 1 :(得分:0)