You've already forked testing-go-code-with-postgres
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:
2
LICENSE
2
LICENSE
@ -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:
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
@ -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,
|
||||||
|
@ -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())
|
||||||
|
Reference in New Issue
Block a user