pashagolub / pgxmock

pgx mock driver for golang to test database interactions
Other
386 stars 49 forks source link

Request WithNamedArgs or something similar #164

Closed dropwhile closed 1 year ago

dropwhile commented 1 year ago

Is your feature request related to a problem? Please describe.

I have started using pgx.NamedArgs (pgx/v5) with some of my queries, and this presents a bit of a challenge with the current WithArgs matcher.

I am currently using a workaround like this:

type pgxNamedArgsArgument struct {
    args pgx.NamedArgs
    keys []string
}

func NewPgxNamedArgsMatcher(args pgx.NamedArgs) pgxmock.Argument {
    keys := Keys(args)
    slices.Sort(keys)
    return pgxNamedArgsArgument{args, keys}
}

func (a pgxNamedArgsArgument) Match(x interface{}) bool {
    if namedArgs, ok := x.(pgx.NamedArgs); ok {
        // match all keys
        nk := Keys(namedArgs)
        slices.Sort(nk)
        if !slices.Equal(nk, a.keys) {
            return false
        }
        // match all values
        for k := range a.args {
            if matcher, ok := a.args[k].(pgxmock.Argument); ok {
                if !matcher.Match(namedArgs[k]) {
                    return false
                }
                continue
            }
            if !reflect.DeepEqual(a.args[k], namedArgs[k]) {
                return false
            }
        }
        return true
    }
    return false
}

And using this matcher thusly:

mock.ExpectQuery("^INSERT INTO some_table (.+)").
    WithArgs(NewPgxNamedArgsMatcher(pgx.NamedArgs{
        "thingID": thingID,
        "thingVal":  pgxmock.AnyArg(),
    })).
    WillReturnRows(
        pgxmock.NewRows([]string{"column1", "column2").
            AddRow("result1", "result2")
    )

My workaround seems to be working ok for now, but I'd like to see if there is a better way to do this with pgxmock. And if not currently, maybe there is a possibility to add something like a WithNamedArgs method that would accept either a pgx.NamedArgs (as my example above does), or just a map[string]interface{} where values could be pgxmock.Arguments or deepequal compared values, but usable to check against pgx.NamedArgs.

pashagolub commented 1 year ago

Hello,

Sounds cool! Do you want to try to work on pull request? It'd be great to have you as an author of the idea and the implementation.

dropwhile commented 1 year ago

@pashagolub I opened a PR. 👍

dropwhile commented 1 year ago

@pashagolub thanks for all your help (and for finishing things up)! <3

pashagolub commented 1 year ago

My pleasure. Thank you for the new feature!