Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何将go sqlmock WithArgs()与可变数量的参数一起使用?_Go - Fatal编程技术网

如何将go sqlmock WithArgs()与可变数量的参数一起使用?

如何将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

我使用go-sqlmock()测试一个接收可变数量参数的函数(为了简单起见,我简化了该函数,并去掉了大部分代码):

测试结果如下所示:

// 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{,…}