调用回滚事务,这是意料之外的,下一个期望是:ExpectedQuery。

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

call to Rollback transaction, was not expected, next expectation is: ExpectedQuery

问题

我正在尝试编写下面的测试,其他测试都正常工作,但是我在UPDATE查询方面遇到了问题。

func TestDeleteWorkspace(t *testing.T) {
    conn, mock, repository, err := setup()
    defer conn.Close()
    assert.NoError(t, err)

    uid := uuid.New()

    // mock.ExpectBegin()
    mock.ExpectQuery(regexp.QuoteMeta(`UPDATE "workspaces" SET`)).WithArgs(sqlmock.AnyArg(), uid)
    // mock.ExpectCommit()

    var e bool
    e, err = repository.Delete(uid)
    assert.NoError(t, err)
    assert.True(t, e)

    err = mock.ExpectationsWereMet()
    assert.NoError(t, err)
}

repository.Delete执行了这个查询:

func (r *WorkspaceRepository) Delete(id any) (bool, error) {
    if err := r.db.Delete(&model.Workspace{}, "id = ?", id).Error; err != nil {
        return false, nil
    }

    return true, nil
}

它运行了这个查询:

UPDATE "workspaces" SET "deleted_at"='2022-07-04 09:09:20.778' WHERE id = 'c4610193-b43a-4ed7-9ed6-9d67b3f97502' AND "workspaces"."deleted_at" IS NULL

我正在使用软删除,所以是一个UPDATE查询而不是DELETE查询。

然而,我得到了以下错误:

workspace_test.go:169: 
    Error Trace:    workspace_test.go:169
    Error:          Received unexpected error:
                    there is a remaining expectation which was not matched: ExpectedQuery => expecting Query, QueryContext or QueryRow which:
                      - matches sql: 'UPDATE "workspaces" SET'
                      - is with arguments:
                        0 - 28e7aa46-7a22-4dc7-b3ce-6cf02af525ca
                        1 - {}

我做错了什么?

编辑:这是一个软删除操作,所以是UPDATE而不是DELETE。

我的模型:

type Workspace struct {
    ID        uuid.UUID      `gorm:"type:uuid;default:uuid_generate_v4()" json:"id"`
    Name      string         `gorm:"not null,type:text" json:"name"`
    CreatedAt time.Time      `gorm:"autoCreateTime" json:"create_time"`
    UpdatedAt time.Time      `gorm:"autoUpdateTime" json:"update_time"`
    DeletedAt gorm.DeletedAt `gorm:"index->" json:"-"`
}
英文:

I am trying to wrote this test bellow, other tests works fine, however I am having problems with the UPDATE query

func TestDeleteWorkspace(t *testing.T) {
	conn, mock, repository, err := setup()
	defer conn.Close()
	assert.NoError(t, err)

	uid := uuid.New()

	// mock.ExpectBegin()
	mock.ExpectQuery(regexp.QuoteMeta(`UPDATE "workspaces" SET`)).WithArgs(sqlmock.AnyArg(), uid)
	// mock.ExpectCommit()

	var e bool
	e, err = repository.Delete(uid)
	assert.NoError(t, err)
	assert.True(t, e)

	err = mock.ExpectationsWereMet()
	assert.NoError(t, err)
}

repository.Delete does this query

func (r *WorkspaceRepository) Delete(id any) (bool, error) {
	if err := r.db.Delete(&model.Workspace{}, "id = ?", id).Error; err != nil {
		return false, nil
	}

	return true, nil
}

Which runs this query

UPDATE "workspaces" SET "deleted_at"='2022-07-04 09:09:20.778' WHERE id = 'c4610193-b43a-4ed7-9ed6-9d67b3f97502' AND "workspaces"."deleted_at" IS NULL

I am using Soft-Delete, that is why it is an UPDATE and not a DELETE query

However, I get the following error

    workspace_test.go:169: 
                Error Trace:    workspace_test.go:169
                Error:          Received unexpected error:
                                there is a remaining expectation which was not matched: ExpectedQuery => expecting Query, QueryContext or QueryRow which:
                                  - matches sql: 'UPDATE "workspaces" SET'
                                  - is with arguments:
                                    0 - 28e7aa46-7a22-4dc7-b3ce-6cf02af525ca
                                    1 - {}

What I am doing wrong?

EDIT: It is a soft-delete operation, that why is a UPDATE and not a DELETE

My model

type Workspace struct {
	ID        uuid.UUID      `gorm:"type:uuid;default:uuid_generate_v4()" json:"id"`
	Name      string         `gorm:"not null,type:text" json:"name"`
	CreatedAt time.Time      `gorm:"autoCreateTime" json:"create_time"`
	UpdatedAt time.Time      `gorm:"autoUpdateTime" json:"update_time"`
	DeletedAt gorm.DeletedAt `gorm:"index,->" json:"-"`
}

答案1

得分: 1

错误消息相当自解释。

这是你的查询语句:

'UPDATE "workspaces" SET "deleted_at"=$1 WHERE id = $2 AND "workspaces"."deleted_at" IS NULL'

它包含两个参数:

"deleted_at"=$1 WHERE id = $2

你在 SQL 模拟中只设置了一个参数:

.WithArgs(uid)

你需要在模拟中发送两个参数。

在测试中使用 Time.Now() 不可靠,因为该值偶尔会与你在代码中设置的值相差几纳秒,导致测试失败。

一个快速而简单的解决方法是使用 sqlmock.AnyArg()

.WithArgs(sqlmock.AnyArg(), uid)

一个更复杂的替代方法是编写自定义的 Argument,它检查类型并将值与 time.Now() 进行比较。差异应该小于几秒钟。

参考示例:https://github.com/DATA-DOG/go-sqlmock#matching-arguments-like-timetime

英文:

Error message is quite self-explanatory.

This is your query:

'UPDATE "workspaces" SET "deleted_at"=$1 WHERE id = $2 AND "workspaces"."deleted_at" IS NULL'

it includes 2 arguments:

"deleted_at"=$1 WHERE id = $2

You set only 1 in your SQL mock:

.WithArgs(uid)

You need to send both arguments in mock.

It is not reliable to use Time.Now() in test because that value occasionally is going to be a few nanoseconds different from the value you set in code and test will fail.

The quick and dirty fix is to use sqlmock.AnyArg():

.WithArgs(sqlmock.AnyArg(), uid)

A more sophisticated alternative is to write custom Argument that checks type and compares value with time.Now(). Difference should be less than a few seconds.

See an example: https://github.com/DATA-DOG/go-sqlmock#matching-arguments-like-timetime

huangapple
  • 本文由 发表于 2022年7月3日 03:11:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/72841815.html
匿名

发表评论

匿名网友

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

确定