[英]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 可以是以下类型之一:
所以,正确答案是
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.