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:"-"`
}
CodePudding user response:
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