1
0
mirror of https://github.com/xorcare/testing-go-code-with-postgres.git synced 2025-07-03 23:30:31 +02:00

Migrate to sql.DB driver

This is to reduce dependency on a particular driver. In the future this
will be used to implement different ways of cleaning the database.
This commit is contained in:
Vasiliy Vasilyuk
2024-02-17 16:38:16 +03:00
parent 883c9e0805
commit 912e9c9ab0
5 changed files with 30 additions and 32 deletions

View File

@ -1,6 +1,6 @@
BSD 3-Clause License BSD 3-Clause License
Copyright (c) 2023, Vasiliy Vasilyuk Copyright (c) 2023-2024, Vasiliy Vasilyuk
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met: modification, are permitted provided that the following conditions are met:

View File

@ -1,4 +1,4 @@
// Copyright (c) 2023 Vasiliy Vasilyuk. All rights reserved. // Copyright (c) 2023-2024 Vasiliy Vasilyuk. All rights reserved.
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
@ -7,6 +7,7 @@ package testingpg
import ( import (
"context" "context"
"crypto/rand" "crypto/rand"
"database/sql"
"encoding/base64" "encoding/base64"
"fmt" "fmt"
"net/url" "net/url"
@ -16,7 +17,7 @@ import (
"time" "time"
"unicode" "unicode"
"github.com/jackc/pgx/v5/pgxpool" _ "github.com/jackc/pgx/v5/stdlib"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
@ -40,8 +41,8 @@ type Postgres struct {
url string url string
ref string ref string
pgxpool *pgxpool.Pool sqlDB *sql.DB
pgxpoolOnce sync.Once sqlDBOnce sync.Once
} }
func newPostgres(t TestingT) *Postgres { func newPostgres(t TestingT) *Postgres {
@ -71,12 +72,12 @@ func (p *Postgres) URL() string {
return p.url return p.url
} }
func (p *Postgres) PgxPool() *pgxpool.Pool { func (p *Postgres) DB() *sql.DB {
p.pgxpoolOnce.Do(func() { p.sqlDBOnce.Do(func() {
p.pgxpool = newPGxPool(p.t, p.URL()) p.sqlDB = open(p.t, p.URL())
}) })
return p.pgxpool return p.sqlDB
} }
func (p *Postgres) cloneFromReference() *Postgres { func (p *Postgres) cloneFromReference() *Postgres {
@ -90,7 +91,7 @@ func (p *Postgres) cloneFromReference() *Postgres {
p.ref, p.ref,
) )
_, err := p.PgxPool().Exec(context.Background(), sql) _, err := p.DB().ExecContext(context.Background(), sql)
require.NoError(p.t, err) require.NoError(p.t, err)
// Automatically drop database copy after the test is completed. // Automatically drop database copy after the test is completed.
@ -100,7 +101,7 @@ func (p *Postgres) cloneFromReference() *Postgres {
ctx, done := context.WithTimeout(context.Background(), time.Minute) ctx, done := context.WithTimeout(context.Background(), time.Minute)
defer done() defer done()
_, err := p.PgxPool().Exec(ctx, sql) _, err := p.DB().ExecContext(ctx, sql)
require.NoError(p.t, err) require.NoError(p.t, err)
}) })
@ -169,17 +170,14 @@ func replaceDBName(t TestingT, dataSourceURL, dbname string) string {
return r.String() return r.String()
} }
func newPGxPool(t TestingT, dataSourceURL string) *pgxpool.Pool { func open(t TestingT, dataSourceURL string) *sql.DB {
ctx, done := context.WithTimeout(context.Background(), 1*time.Second) db, err := sql.Open("pgx/v5", dataSourceURL)
defer done()
pool, err := pgxpool.New(ctx, dataSourceURL)
require.NoError(t, err) require.NoError(t, err)
// Automatically close connection after the test is completed. // Automatically close connection after the test is completed.
t.Cleanup(func() { t.Cleanup(func() {
pool.Close() db.Close()
}) })
return pool return db
} }

View File

@ -1,4 +1,4 @@
// Copyright (c) 2023 Vasiliy Vasilyuk. All rights reserved. // Copyright (c) 2023-2024 Vasiliy Vasilyuk. All rights reserved.
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
@ -50,7 +50,7 @@ func TestNewPostgres(t *testing.T) {
// Act // Act
var version string var version string
err := postgres.PgxPool().QueryRow(ctx, "SELECT version();").Scan(&version) err := postgres.DB().QueryRowContext(ctx, "SELECT version();").Scan(&version)
// Assert // Assert
require.NoError(t, err) require.NoError(t, err)
@ -70,8 +70,8 @@ func TestNewPostgres(t *testing.T) {
// Act // Act
const sql = `CREATE TABLE "no_conflict" (id integer PRIMARY KEY)` const sql = `CREATE TABLE "no_conflict" (id integer PRIMARY KEY)`
_, err1 := postgres1.PgxPool().Exec(ctx, sql) _, err1 := postgres1.DB().ExecContext(ctx, sql)
_, err2 := postgres2.PgxPool().Exec(ctx, sql) _, err2 := postgres2.DB().ExecContext(ctx, sql)
// Assert // Assert
require.NoError(t, err1) require.NoError(t, err1)

View File

@ -1,4 +1,4 @@
// Copyright (c) 2023 Vasiliy Vasilyuk. All rights reserved. // Copyright (c) 2023-2024 Vasiliy Vasilyuk. All rights reserved.
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
@ -6,18 +6,18 @@ package testing_go_code_with_postgres
import ( import (
"context" "context"
"database/sql"
"fmt" "fmt"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/jackc/pgx/v5/pgxpool"
) )
func NewUserRepository(db *pgxpool.Pool) *UserRepository { func NewUserRepository(db *sql.DB) *UserRepository {
return &UserRepository{db: db} return &UserRepository{db: db}
} }
type UserRepository struct { type UserRepository struct {
db *pgxpool.Pool db *sql.DB
} }
func (r *UserRepository) ReadUser(ctx context.Context, userID uuid.UUID) (User, error) { func (r *UserRepository) ReadUser(ctx context.Context, userID uuid.UUID) (User, error) {
@ -25,7 +25,7 @@ func (r *UserRepository) ReadUser(ctx context.Context, userID uuid.UUID) (User,
user := User{} user := User{}
row := r.db.QueryRow(ctx, sql, userID) row := r.db.QueryRowContext(ctx, sql, userID)
err := row.Scan(&user.ID, &user.Username, &user.CreatedAt) err := row.Scan(&user.ID, &user.Username, &user.CreatedAt)
if err != nil { if err != nil {
@ -40,7 +40,7 @@ func (r *UserRepository) ReadUser(ctx context.Context, userID uuid.UUID) (User,
func (r *UserRepository) CreateUser(ctx context.Context, user User) error { func (r *UserRepository) CreateUser(ctx context.Context, user User) error {
const sql = `INSERT INTO users (user_id, username, created_at) VALUES ($1,$2,$3);` const sql = `INSERT INTO users (user_id, username, created_at) VALUES ($1,$2,$3);`
_, err := r.db.Exec( _, err := r.db.ExecContext(
ctx, ctx,
sql, sql,
user.ID, user.ID,

View File

@ -1,4 +1,4 @@
// Copyright (c) 2023 Vasiliy Vasilyuk. All rights reserved. // Copyright (c) 2023-2024 Vasiliy Vasilyuk. All rights reserved.
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
@ -36,7 +36,7 @@ func TestUserRepository_CreateUser(t *testing.T) {
// Arrange // Arrange
postgres := testingpg.New(t) postgres := testingpg.New(t)
repo := rootpkg.NewUserRepository(postgres.PgxPool()) repo := rootpkg.NewUserRepository(postgres.DB())
user := newFullyFiledUser() user := newFullyFiledUser()
@ -57,7 +57,7 @@ func TestUserRepository_CreateUser(t *testing.T) {
// Arrange // Arrange
postgres := testingpg.New(t) postgres := testingpg.New(t)
repo := rootpkg.NewUserRepository(postgres.PgxPool()) repo := rootpkg.NewUserRepository(postgres.DB())
user := newFullyFiledUser() user := newFullyFiledUser()
@ -85,7 +85,7 @@ func TestUserRepository_ReadUser(t *testing.T) {
// Arrange // Arrange
postgres := testingpg.New(t) postgres := testingpg.New(t)
repo := rootpkg.NewUserRepository(postgres.PgxPool()) repo := rootpkg.NewUserRepository(postgres.DB())
// Act // Act
_, err := repo.ReadUser(context.Background(), uuid.New()) _, err := repo.ReadUser(context.Background(), uuid.New())