Help with mocking returning pgx.Row from QueryRow method #51
-
We are using separate database connections for read and write proxies, so I've created a type DBConnector interface {
Begin(ctx context.Context) (pgx.Tx, error)
BeginFunc(ctx context.Context, f func(pgx.Tx) error) error
CloseConnection()
Exec(ctx context.Context, sql string, args ...interface{}) (pgconn.CommandTag, error)
Query(ctx context.Context, sql string, args ...interface{}) (pgx.Rows, error)
QueryRow(ctx context.Context, sql string, args ...interface{}) (pgx.Row, error)
NewConnection(ctx context.Context, dp DBProxies) error
}
type AWSDB struct {
reader *pgxpool.Pool
writer *pgxpool.Pool
} The // QueryRow wraps the *pgxpool.Pool QueryRow method using the AWSDB reader connection
func (d *AWSDB) QueryRow(ctx context.Context, sql string, args ...interface{}) (pgx.Row, error) {
if d.reader == nil {
return nil, errors.New("reader pool not created")
}
return d.reader.QueryRow(ctx, sql, args...), nil
} And so some code that implements this would look like this: func getUserData(ctx context.Context, dbc db.DBConnector, c string) (row, error) {
query := `
SELECT
ap.external_acct_id as external_acct_id,
apt.user_status as user_status,
ap.acct_uuid as acct_uuid,
ap.user_id as user_id
FROM account_profile ap
JOIN app_user_type apt ON apt.user_id = ap.user_id
WHERE ap.id = $1;
`
pgRow, err := dbc.QueryRow(ctx, query, c)
if err != nil {
return row{}, err
}
var r row
if err := pgRow.Scan(
&r.ExternalAcctID,
&r.UserStatus,
&r.AcctUUID,
&r.UserID,
); err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return row{}, errors.New("no user found with id " + c)
} else {
return row{}, err
}
}
return r, nil
} I'd like to be able to write unit tests around this type mockAWSDB struct {
db.DBConnector
reader pgxmock.PgxPoolIface
}
func (md *mockAWSDB) NewConnection(ctx context.Context, dp db.DBProxies) error {
pool, err := pgxmock.NewPool()
if err != nil {
return err
}
switch dp {
case db.Read:
md.reader = pool
default:
return fmt.Errorf("db proxy " + string(db.Read) + " only supported")
}
return nil
}
// This is where I'd like to create the mock `pgx.Row` value to return expected values
func (md *mockAWSDB) QueryRow(ctx context.Context, sql string, args ...interface{}) (pgx.Row, error) {
} I'm falling short here and don't know how to make this |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 2 replies
-
Hello, the key trick here is to use interface instead of the real type AWSDB struct {
reader DBConnector
writer DBConnector
} Then in the tests instead of creating a real Instead of using the real |
Beta Was this translation helpful? Give feedback.
Hello,
the key trick here is to use interface instead of the real
pgx
objects, e.g.Then in the tests instead of creating a real
pgxpool.Pool
you should create apgxmock
object. Check here the example:https://github.com/pashagolub/pgxmock/blob/master/examples/basic/
Instead of using the real
pgxpool.Pool
as an argument in therecordStats()
function, we use thePgxIface
interface. Which allows us to usepgxmock
during tests and the real connection during work.