We are using separate database connections for read and write proxies, so I've created a DBConnector
interface and a struct that implements it that look like this:
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 AWSBD
struct has methods like this to wrap the pgxpool.Pool
methods using the intended reader or writer connection.
// 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 getUserData
function to check responses for things like no rows found, etc. My approach has been to create a mock db connection that implements my db.DBConnector
interface like 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 QueryRow
method to return the pgx.Row
value that I want using the underlying pgxmock.PgxPoolIface
QueryRow
method. Any help would be appreciated, thanks.