如何将go sqlmock WithArgs()与可变数量的参数一起使用?
我使用go-sqlmock()测试一个接收可变数量参数的函数(为了简单起见,我简化了该函数,并去掉了大部分代码): 测试结果如下所示:如何将go sqlmock WithArgs()与可变数量的参数一起使用?,go,Go,我使用go-sqlmock()测试一个接收可变数量参数的函数(为了简单起见,我简化了该函数,并去掉了大部分代码): 测试结果如下所示: // rows := ... actions := []string{"click", "event"} mock.ExpectQuery(`^select .*`).WithArgs(actions).WillReturnRows(rows) hits, err := getHits(db, actions...) if mockErr := mock.Exp
// 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: ...
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:
如果我像这样更改测试:
mock.ExpectQuery(`^select .*`).WithArgs(actions[0], actions[1]).WillReturnRows(rows)
然后我得到这个输出:
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: ...
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])
这显然是我不想做的,因为我不知道有多少动作
有人知道我如何修复或调试这个问题吗?我找到了一种解决问题的方法:如果我将字符串片段转换为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(查询,操作…)
不起作用;这导致无法将操作(类型[]字符串)用作db的参数中的类型[]接口{}。使用[]接口{}
查询接受的答案将适用于字符串,但可能会对其他类型抛出错误
简短回答
actions := []driver.Value{"click", "event"}
mock.ExpectQuery(`^select .*`).WithArgs(actions...).WillReturnRows(rows)
长答案
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)
一个更干净的解决方案是使用这个
/* 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
这是文档中的参考文件是否操作…
不起作用?@Flimzy nope;编译器抱怨:无法将操作(类型[]字符串)用作mock.ExpectQuery(^select.*)的参数中的类型[]driver.Value。WithArgs
将操作
转换为类型[]driver.Value
。@Flimzy不幸的是,这会产生与案例2中完全相同的输出。抱歉,哪种情况是2?如果int64属于driver.Value中允许的类型,那么为什么[]int64不能工作?您可以执行[]driver.Value{,…}