使用 go-sqlmock 模拟 gorm“更新”时出现“无法匹配实际 sql”错误?

sof*_*fs1 2 go go-gorm go-sqlmock

存储库.go

\n\n
func (repo *Repository) Update(info *model.Requests) error{\n   if info == nil{\n      return nil\n   }\n   columnChanges := map[string]interface{}{\n      status:       \xe2\x80\x9ccompleted",\n   }\n   if err := repo.db.Table(\xe2\x80\x9crequests").Model(info).Where(fmt.Sprintf("%s = ? AND  %s = ? AND %s = ? AND %s = ?",\n      requestID, systemID, requestType, status),info.RequestID, info.SystemID, info.RequestType,\xe2\x80\x9dprogress").Updates(columnChanges).Error; err != nil {\n      return err\n   }\n   return nil\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

嘲笑

\n\n

存储库_test.go

\n\n
func TestRepository_Update(t *testing.T) {\n   type testData struct {\n      input     *model.Requests\n      queryString string\n      queryArgs   []driver.Value\n      updateErr   error\n      hasErr    bool\n   }\n\n   db, mock, _ := sqlmock.New()\n   defer db.Close()\n   dbInstance, _ := gorm.Open("postgres", db)\n\n   testDataList := []testData{\n        {\n   input: &model.Requests{\n      RequestID: 4,\n      SystemID: 2,\n      RequestType: \xe2\x80\x9cmobile",\n      Status: \xe2\x80\x9ccompleted",\n   },\n   queryString: `UPDATE "requests" SET "status" = $1 WHERE (\xe2\x80\x9crequest_id" = $2 AND \xe2\x80\x9csystem_id" = $3 AND \xe2\x80\x9crequest_type" = $4 AND "status" = $5) `,\n   queryArgs:   []driver.Value{\xe2\x80\x9ccompleted", 2, 4, \xe2\x80\x9cmobile", \xe2\x80\x9cprogress"},\n   updateErr:   nil,\n   hasErr: false,\n},\n}\n\n    for _, data := range testDataList {\n      repo := Repository(zerolog.Nop(), dbInstance)\n\n      if data.queryString != "" {\n         mock.ExpectBegin()\n         m := mock.ExpectExec(data.queryString).WithArgs(data.queryArgs...)\n         if data.hasErr {\n            m.WillReturnError(data.updateErr)\n         } else {\n            m.WillReturnResult(sqlmock.NewResult(1, 1))\n         }\n         mock.ExpectCommit()\n      }\n\n      resultErr := repo.Requests(data.input)\n\n      if data.hasErr {\n         assert.NotNil(t, resultErr)\n      } else {\n         assert.Nil(t, resultErr) //Error thrown in this line \n      }\n\n      if err := mock.ExpectationsWereMet(); err != nil {\n         t.Errorf("there were unfulfilled expectations: %s", err)\n      }\n   }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

错误 I\xe2\x80\x99m 获取

\n\n
ExecQuery: could not match actual sql: "UPDATE "requests" SET "status" = $1 WHERE (request_id = $2 AND system_id = $3 AND request_type = $4 AND status = $5)" with expected regexp "UPDATE "requests" SET "status" = $1 WHERE ("request_id" = $2 AND "system_id" = $3 AND "request_type" = $4 AND "status" = $5)\xe2\x80\x9d\n\n\n\n            Error Trace:    repository_test.go:<line number>\n            Error:          Expected nil, but got: &errors.errorString{s:"ExecQuery: could not match actual sql: \\"UPDATE \\"requests\\" SET \\"status\\" = $1 WHERE (request_id = $2 AND system_id = $3 AND request_type = $4 AND status = $5)\\" with expected regexp \\"UPDATE \\"requests\\" SET \\"status\\" = $1 WHERE (\\\xe2\x80\x9drequest_id\\" = $2 AND \\\xe2\x80\x9dsystem_id\\" = $3 AND \\\xe2\x80\x9drequest_type\\" = $4 AND \\"status\\" = $5)\\""}\n            Test:           Repository_Update\n    repository_test.go:<lineNumber>: there were unfulfilled expectations: there is a remaining expectation which was not matched: ExpectedExec => expecting Exec or ExecContext which:\n          - matches sql: \'UPDATE "requests" SET "status" = $1 WHERE (\xe2\x80\x9crequest_id" = $2 AND \xe2\x80\x9csystem_id" = $3 AND \xe2\x80\x9crequest_type" = $4 AND "status" = $5) \'\n          - is with arguments:\n            0 - success\n            1 - 2\n            2 - 4\n            3 - image\n            4 - pending\n          - should return Result having:\n              LastInsertId: 1\n              RowsAffected: 1\n
Run Code Online (Sandbox Code Playgroud)\n\n

当我将 gorm 日志级别设置为 true 时,这是我看到的实际 SQL

\n\n
UPDATE "requests" SET "status" = \xe2\x80\x98completed\'  WHERE (request_id = 5 AND  system_id = 1 AND request_type = \xe2\x80\x98mobile\' AND status = \xe2\x80\x98progress\')\n
Run Code Online (Sandbox Code Playgroud)\n\n

我尝试更改ExpectExecExpectPrepare().ExpectExecormock.ExpectQuery(regexp.QuoteMeta以及其他票证中 go-sqlmock 问题中提到的其他选项。他们都没有工作。为此困扰了2天。请帮忙。

\n

Ged*_*nas 6

原因是您没有转义查询字符串的正则表达式。Sqlmock 期望您期望的正则表达式。

现在,如果您想匹配精确的查询字符串,而不是它的一部分。您可以指定 sqlmock 模拟选项,如下所示:

db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
Run Code Online (Sandbox Code Playgroud)

答案就在文档中,如果你阅读一次 api 文档,这可以节省你的时间。