If you have been using sqlmock to mock database queries then, you might have or will encounter errors such as sql error unsupported []string, a slice of string
if one of the args in the query is a byte slice.
This is cause the go std/sql driver doesn’t understand or support types other than the std ones.
Below are the types supported by the driver.Value
interface.
// Value is a value that drivers must be able to handle.
// It is either nil, a type handled by a database driver's [NamedValueChecker]
// interface, or an instance of one of these types:
int64
float64
bool
[]byte
string
time.Time
So for user or driver defined types such as sql.NullString
, pq.StringArray
, we need to implement the ValueConverter
interface. Source here.
The workaround for the above issue is to pass our own Custom Converter to the sqlmock which handles all the data types.
More discussion here.
type CustomConverter struct{}
func (s CustomConverter) ConvertValue(v interface{}) (driver.Value, error) {
switch v.(type) {
case string:
return v.(string), nil
case []string:
return v.([]string), nil
case int:
return v.(int), nil
case bool:
return v.(bool), nil
case uint64:
return v.(uint64), nil
case pq.StringArray:
var result []string
for _, val := range v.(pq.StringArray) {
result = append(result, val)
}
return result, nil
case MessageAuthor:
return string(v.(MessageAuthor)), nil
case sql.NullString:
if v.(sql.NullString).Valid {
return v.(sql.NullString).String, nil
}
return nil, nil
case MessageStatus:
return string(v.(MessageStatus)), nil
default:
return nil, fmt.Errorf("cannot convert %T with value %v", v, v)
}
}
// init
func GetMockDB() (*sql.DB, sqlmock.Sqlmock, error) {
return sqlmock.New(sqlmock.ValueConverterOption(CustomConverter{}))
}
This will hopefully pass all your test cases and you sleep soundly.