go-sqlmock
go-sqlmock copied to clipboard
Argument matching for queries using unpacked slices
trafficstars
I have a sqlx.Query being called on a named query with multiple parameters. You can see a working example, but here's the abridged version:
type myStruct struct {
ColumnA string `db:"columnA"`
ColumnB string `db:"columnB"`
ColumnC []string `db:"columnC"`
}
func runQuery(db *sqlx.DB, arguments myStruct) ([]myStruct, error) {
namedQuery := "SELECT * FROM my_table WHERE columnA = :columnA AND columnB = :columnB AND columnC IN (:columnC)"
query, args, _ := sqlx.Named(namedQuery, arguments)
query, args, _ = sqlx.In(query, args...)
query = db.Rebind(query)
rows, err := db.Queryx(query, args...)
if err != nil {
return nil, fmt.Errorf("error querying: %s", err)
}
//…
}
And then a test case like so
mockDb, mock, err := sqlmock.New()
sqlxDB := sqlx.NewDb(mockDb, "sqlmock")
toQuery := myStruct{
ColumnA: "testA",
ColumnB: "testB",
ColumnC: []string{"testC", "testD"},
}
queryArgs := []string{"testA", "testB", "testC", "testD"}
returnRows := mock.NewRows([]string{"columnA", "columnB"}).AddRow("returnA", "returnB")
mock.ExpectQuery("SELECT \\* FROM my_table ").WithArgs(queryArgs).WillReturnRows(returnRows)
_, err = runQuery(sqlxDB, toQuery)
if err != nil {
log.Println(err)
return
}
Which results in this error message:
Query 'SELECT * FROM my_table WHERE columnA = ? AND columnB = ? AND columnC IN (?, ?)',
arguments do not match: expected 1, but got 4 arguments
The error makes sense, because I am passing queryArgs ([]string) to WithArgs, while the actual Queryx(query, args...) method gets an unpacked []interface{} as its arguments. But doing a similar AddRow(queryArgs...) results in:
cannot use queryArgs (variable of type []string) as []driver.Value value in argument to mock.ExpectQuery
Which leads me to my question: How can I pass an array to WithArgs that would match the unpacked arguments passed to Queryx?
I know I could hard code it, but in the non-simplified version of this code, the number of arguments is variable for each test case.