簡體   English   中英

如何使用帶有可變數量參數的 go-sqlmock WithArgs()?

[英]How to use go-sqlmock WithArgs() with a variable number of arguments?

我使用 go-sqlmock ( https://godoc.org/github.com/DATA-DOG/go-sqlmock ) 來測試接收可變數量參數的函數(為了簡單起見,我簡化了該函數並剝離了大部分代碼):

func getHits(db *sql.DB, actions ...string) (hits []Hit, err error) {
   // ...
   query := `select * from table where action in (?,?)`
   rows, err := db.Query(query, actions)
   // ...
}

測試看起來像這樣:

// rows := ...
actions := []string{"click", "event"}
mock.ExpectQuery(`^select .*`).WithArgs(actions).WillReturnRows(rows)
hits, err := getHits(db, actions...)
if mockErr := mock.ExpectationsWereMet(); mockErr != nil {
    log.Fatalf("there were unfulfilled expections: %s", mockErr)
}

然后我得到這個輸出:

2017/12/21 10:38:23 there were unfulfilled expections: there is a remaining expectation which was not matched: ExpectedQuery => expecting Query or QueryRow which:
- matches sql: '^select .*'
- is with arguments:
  0 - [click event]
- should return rows: ...

如果我像這樣更改測試:

mock.ExpectQuery(`^select .*`).WithArgs(actions[0], actions[1]).WillReturnRows(rows)

然后我得到這個輸出:

2017/12/21 10:44:41 there were unfulfilled expections: there is a remaining expectation which was not matched: ExpectedQuery => expecting Query or QueryRow which:
- matches sql: '^select .*'
- is with arguments:
  0 - click
  1 - event
- should return rows:

我唯一能讓它通過的是通過調用:

db.Query(query, actions[0], actions[1])

這顯然是我不想做的,因為我不知道操作的數量......

有沒有人知道我如何修復或調試它?

使用[]interface{}接受的答案適用於字符串,但它可能會引發其他類型的錯誤。

簡答

actions := []driver.Value{"click", "event"}
mock.ExpectQuery(`^select .*`).WithArgs(actions...).WillReturnRows(rows)

長答案

參數需要driver.Value 引用,並且 driver.Value 可以是以下類型之一

  • int64
  • 浮動64
  • 布爾值
  • []字節
  • 細繩
  • 時間.時間

所以,正確答案是

actions := []driver.Value{"click", "event"}
mock.ExpectQuery(`^select .*`).WithArgs(actions...).WillReturnRows(rows)

我找到了解決問題的方法:如果我將字符串片段轉換為 db.Query 的接口片段,它就可以正常工作:

boundValues := make([]interface{}, len(actions))

for i, val := range actions {
    boundValues[i] = val
}

rows, err := db.Query(query, boundValues...)

然后對於測試:

mock.ExpectQuery(`^select .*`).WithArgs(actions[0], actions[1]).WillReturnRows(rows)

注意:僅傳遞db.Query(query, actions...)不起作用; 這導致cannot use actions (type []string) as type []interface {} in argument to db.Query

一個更清潔的解決方案是使用它。

/* Prepare database mock */
type AnyNumber struct{}

// Match satisfies sqlmock.Argument interface
func (a AnyNumber) Match(v driver.Value) bool {
    _, ok := v.(float64)
    return ok
}

然后使用AnyNumber{}作為WithArgs的參數

這是文檔中的參考單擊此處

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM