简体   繁体   English

如何使用带有可变数量参数的 go-sqlmock WithArgs()?

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

I use go-sqlmock ( https://godoc.org/github.com/DATA-DOG/go-sqlmock ) to test a function that receives a variable number of arguments (I simplified the function for the sake of simplicity and stripped out most of the code):我使用 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)
   // ...
}

The tests look like that:测试看起来像这样:

// 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)
}

Then I get this output:然后我得到这个输出:

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: ...

If I change the tests like this:如果我像这样更改测试:

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

Then I get this output:然后我得到这个输出:

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:

The only I can make it pass is by calling :我唯一能让它通过的是通过调用:

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

which is what I obviously don't want to do as I don't know the number of actions...这显然是我不想做的,因为我不知道操作的数量......

Does anyone have an idea on how I could fix or debug this ?有没有人知道我如何修复或调试它?

Accepted answer using []interface{} would work for string but it can throw an error for other types.使用[]interface{}接受的答案适用于字符串,但它可能会引发其他类型的错误。

Short answer简答

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

Long answer长答案

The argument requires driver.Value reference and driver.Value can be one of these types :参数需要driver.Value 引用,并且 driver.Value 可以是以下类型之一

  • int64 int64
  • float64浮动64
  • bool布尔值
  • []byte []字节
  • string细绳
  • time.Time时间.时间

so, the correct answer is所以,正确答案是

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

I found a way to fix my problem : If I convert the slice of strings to a slice of interfaces for db.Query, it works just fine:我找到了解决问题的方法:如果我将字符串片段转换为 db.Query 的接口片段,它就可以正常工作:

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

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

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

Then for the tests:然后对于测试:

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

NOTE: passing just db.Query(query, actions...) does not work;注意:仅传递db.Query(query, actions...)不起作用; this results in cannot use actions (type []string) as type []interface {} in argument to db.Query这导致cannot use actions (type []string) as type []interface {} in argument to db.Query

A much cleaner solution would be to use this.一个更清洁的解决方案是使用它。

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

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

And then use AnyNumber{} as the argument in WithArgs然后使用AnyNumber{}作为WithArgs的参数

Here is the reference in the docs Click Here这是文档中的参考单击此处

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 当我的程序中有并发查询时如何使用 go-sqlmock? - How to use go-sqlmock when I have concurrent query in my program? 如何在 go-sqlmock 中添加多个结果集? - How can I add multiple result sets in go-sqlmock? 如何为 go-sqlmock 正确设置 Mock Row 和 Query - How to correctly set Mock Row and Query for go-sqlmock 使用 go-sqlmock 创建 gorm 数据库(运行时错误) - Creating a gorm database with go-sqlmock (runtime error) 使用go-sqlmock在SQL查询中获取参数值 - Get argument value in SQL query with go-sqlmock 对于复合 SQL 查询,在 go-sqlmock 中不会使用 args [] 调用查询 - Call to Query with args [], was not expected in go-sqlmock for compound SQL queries Go 单元测试 - 在使用 go-sqlmock 模拟 gorm 时无法将实际 sql 与预期的正则表达式匹配? - Go Unit test - could not match actual sql with expected regexp while mocking gorm using go-sqlmock? mocking gorm `updates` 使用 go-sqlmock 时出现`could not match actual sql` 错误? - `could not match actual sql` error while mocking gorm `updates` using go-sqlmock? 使用 go-sqlmock 问题测试 gorm 将查询与 mock.ExpectQuery 和 regexp.QuoteMeta 进行比较 - testing gorm with go-sqlmock issue comparing queries with mock.ExpectQuery and regexp.QuoteMeta 转到:如何在go中使用func()bool参数? - Go: How to use the func() bool arguments in go?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM