Sqlmock在将整数参数替换为字母数字参数时无法匹配查询。

huangapple go评论79阅读模式
英文:

Sqlmock is not matching the query when replace integer argument with alpha-numeric one

问题

我正在尝试使用go-sqlmock来测试我的数据库函数,但是我无法通过这个测试。

这是我的模型:

type User struct {
	ID            string `gorm:"primaryKey; size:11"`
	FirstName     string `gorm:"NOT NULL; size:255"`
	LastName      string `gorm:"NOT NULL; size:255"`
	Email         string `gorm:"NOT NULL; UNIQUE_INDEX"`
	Password      string `gorm:"NOT NULL"`
	CreatedAt     time.Time
	UpdatedAt     time.Time
	DeletedAt     *time.Time `sql:"index"`
}

这是我的数据库函数:

func (u *userRepo) GetByID(id string) (*user.User, AppError) {
	var user user.User
	if err := u.db.First(&user, id).Error; err != nil {
		return nil, NewNotFoundError(err)
	}
	return &user, nil
}

我有两个测试示例,一个通过了,另一个没有通过。我像这样初始化了sqlmock对象:

sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))

这个测试通过了:

t.Run("Get a user", func(t *testing.T) {
	expected := &user.User{
		Email: "alice@cc.cc",
	}

	u := NewUserRepo(gormDB)

	mock.
		ExpectQuery(
			`SELECT * FROM "users" WHERE "users"."deleted_at" IS NULL AND (("users"."id" = $1)) ORDER BY "users"."id" ASC LIMIT 1`).
		WithArgs("100").
		WillReturnRows(
			sqlmock.NewRows([]string{"email"}).
				AddRow("alice@cc.cc"))

	result, err := u.GetByID("100")

	assert.EqualValues(t, expected, result)
	assert.Nil(t, err)
})

但是这个测试没有通过:

t.Run("Get a user", func(t *testing.T) {
	expected := &user.User{
		Email: "alice@cc.cc",
	}

	u := NewUserRepo(gormDB)

	mock.
		ExpectQuery(
			`SELECT * FROM "users" WHERE "users"."deleted_at" IS NULL AND (("users"."id" = $1)) ORDER BY "users"."id" ASC LIMIT 1`).
		WithArgs("100a").
		WillReturnRows(
			sqlmock.NewRows([]string{"email"}).
				AddRow("alice@cc.cc"))

	result, err := u.GetByID("100a")

	assert.EqualValues(t, expected, result)
	assert.Nil(t, err)
})

你可以看到唯一的区别是我用100a替换了100,因为主键是一个字符串字段。

这是我得到的错误信息:

Query: actual sql: 
"SELECT * FROM "users" WHERE "users"."deleted_at" IS NULL AND ((100a)) ORDER BY "users"."id" ASC LIMIT 1" 
does not equal to expected 
"SELECT * FROM "users" WHERE "users"."deleted_at" IS NULL AND (("users"."id" = $1)) ORDER BY "users"."id" ASC LIMIT 1" 

我不知道我在这里做错了什么,我甚至将$1替换为"$1"也没有起作用。任何帮助将是很好的。谢谢。

英文:

I am trying to test my DB functions using go-sqlmock and I am not able make this one test pass.

Here is my model

type User struct {
	ID            string `gorm:"primaryKey; size:11"`
	FirstName     string `gorm:"NOT NULL; size:255"`
	LastName      string `gorm:"NOT NULL; size:255"`
	Email         string `gorm:"NOT NULL; UNIQUE_INDEX"`
	Password      string `gorm:"NOT NULL"`
	CreatedAt     time.Time
	UpdatedAt     time.Time
	DeletedAt     *time.Time `sql:"index"`
}

Here is my DB function

func (u *userRepo) GetByID(id string) (*user.User, AppError) {
	var user user.User
	if err := u.db.First(&user, id).Error; err != nil {
		return nil, NewNotFoundError(err)
	}
	return &user, nil
}

I have two examples of tests, one is passing but the other does not. I am initializing sqlmock object like this

sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))

This one is working

t.Run("Get a user", func(t *testing.T) {
	expected := &user.User{
		Email: "alice@cc.cc",
	}

	u := NewUserRepo(gormDB)

	mock.
		ExpectQuery(
			`SELECT * FROM "users" WHERE "users"."deleted_at" IS NULL AND (("users"."id" = $1)) ORDER BY "users"."id" ASC LIMIT 1`).
		WithArgs("100").
		WillReturnRows(
			sqlmock.NewRows([]string{"email"}).
				AddRow("alice@cc.cc"))

	result, err := u.GetByID("100")

	assert.EqualValues(t, expected, result)
	assert.Nil(t, err)
})

But this one is not working

t.Run("Get a user", func(t *testing.T) {
	expected := &user.User{
		Email: "alice@cc.cc",
	}

	u := NewUserRepo(gormDB)

	mock.
		ExpectQuery(
			`SELECT * FROM "users" WHERE "users"."deleted_at" IS NULL AND (("users"."id" = $1)) ORDER BY "users"."id" ASC LIMIT 1`).
		WithArgs("100a").
		WillReturnRows(
			sqlmock.NewRows([]string{"email"}).
				AddRow("alice@cc.cc"))

	result, err := u.GetByID("100a")

	assert.EqualValues(t, expected, result)
	assert.Nil(t, err)
})

As you can see the only difference is I replace 100 by 100a which I can do because the primary key is a string field.

And this is the error I am getting

Query: actual sql: 
"SELECT * FROM "users" WHERE "users"."deleted_at" IS NULL AND ((100a)) ORDER BY "users"."id" ASC LIMIT 1" 
does not equal to expected 
"SELECT * FROM "users" WHERE "users"."deleted_at" IS NULL AND (("users"."id" = $1)) ORDER BY "users"."id" ASC LIMIT 1" 

I don't know what I am doing wrong here, I even replaced the $1 by "$1" which also didn't work. Any help would be great. Thanks.

答案1

得分: 1

这个问题的解决方法如下:

首先,我更新了我的DB获取函数:

func (u *userRepo) GetByID(id string) (*user.User, AppError) {
    var user user.User
    if err := u.db.Where("id = ?", id).First(&user).Error; err != nil {
        return nil, NewNotFoundError(err)
    }
    return &user, nil
}

然后,我将我的模拟测试更改为以下内容:

mock.
    ExpectQuery(
        `SELECT * FROM "users" WHERE "users"."deleted_at" IS NULL AND ((id = $1)) ORDER BY "users"."id" ASC LIMIT 1`).
    WithArgs("100a").
    WillReturnRows(
        sqlmock.NewRows([]string{"email"}).
            AddRow("alice@cc.cc"))

result, err := u.GetByID("100a")
英文:

Here is the fix for this issue.

First of all I update my DB get function

func (u *userRepo) GetByID(id string) (*user.User, AppError) {
	var user user.User
	if err := u.db.Where("id = ?", id).First(&user).Error; err != nil {
		return nil, NewNotFoundError(err)
	}
	return &user, nil
}

And changed my mock test to this

mock.
	ExpectQuery(
		`SELECT * FROM "users" WHERE "users"."deleted_at" IS NULL AND ((id = $1)) ORDER BY "users"."id" ASC LIMIT 1`).
	WithArgs("100a").
	WillReturnRows(
		sqlmock.NewRows([]string{"email"}).
			AddRow("alice@cc.cc"))

result, err := u.GetByID("100a")

huangapple
  • 本文由 发表于 2022年9月22日 05:29:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/73807132.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定