How to use gomock with sqlc

780 views Asked by At

I'd like to write unit tests for functions generated by sqlc but I don't understand how to use gomock. I'm new to mocking.

Below I'll describe a bit how sqlc generation works.

So, sqlc generates an interface DBTX:

type DBTX interface {
    Exec(context.Context, string, ...interface{}) (pgconn.CommandTag, error)
    Query(context.Context, string, ...interface{}) (pgx.Rows, error)
    QueryRow(context.Context, string, ...interface{}) pgx.Row
}

func New(db DBTX) *Queries {
    return &Queries{db: db}
}

type Queries struct {
    db DBTX
}

func (q *Queries) WithTx(tx pgx.Tx) *Queries {
    return &Queries{
        db: tx,
    }
}

And an interface Querier with all functions that talks to db (also generated by sqlc). In my case:

type Querier interface {
    CreateCustomer(ctx context.Context, customerID int64) (int64, error)
    CreateExecutor(ctx context.Context, arg CreateExecutorParams) (Executor, error)
    CreateUser(ctx context.Context, arg CreateUserParams) (User, error)
    DeleteUser(ctx context.Context, userID int64) error
    GetUser(ctx context.Context, userID int64) (User, error)
    ListUsers(ctx context.Context) ([]User, error)
}

var _ Querier = (*Queries)(nil)

Example of generated function GetUser:

const getUser = `-- name: GetUser :one
SELECT user_id, email, password FROM "user"
WHERE user_id = $1
`

func (q *Queries) GetUser(ctx context.Context, userID int64) (User, error) {
    row := q.db.QueryRow(ctx, getUser, userID)
    var i User
    err := row.Scan(
        &i.UserID,
        &i.Email,
        &i.Password,
    )
    return i, err
}

To use transactions I created an interface Storage (which contains Querier and all transaction functions) as described here. It looks like this:

type Storage interface {
    Querier
    CreateUserTx(ctx context.Context, arg CreateUserTxParams) (User, error)
}

type SQLStorage struct {
    db *pgxpool.Pool
    *Queries
}

func NewStorage(db *pgxpool.Pool) Storage {
    return &SQLStorage{
        db:      db,
        Queries: New(db),
    }
}

So for example I created a function CreateUserTx that uses Storage.db to make transactions. And now all interactions with database are done through Storage.

And the question is how to mock database to test all functions in Storage. All mocking examples in web seem aren't that complicated. Could you elaborate on how to do that?

1

There are 1 answers

0
Fakhredin Gholamizadeh On

You can see a complete and problem-free service here and compare your problem with the correct service.

Test Connection

func TestMain(m *testing.M) {
    conn, err := sql.Open(dbDriver, dbSource)

    if err != nil {
        log.Fatal("connot connect to db:", err)
    }

    testQueries = New(conn)

    os.Exit(m.Run())
}

Be sure to view my project and your test problems will be solved and you will even get good ideas from it.