diff --git a/README.md b/README.md index a37bdb0..44c0ad9 100644 --- a/README.md +++ b/README.md @@ -76,8 +76,7 @@ total: (statements) 100.0% - Example of test database connection management in [testingpg](https://github.com/xorcare/testing-go-code-with-postgres/tree/main/testingpg) package. -- Example of - integration [tests](https://github.com/xorcare/testing-go-code-with-postgres/blob/main/user_repository_test.go). +- [Example of integration testing with isolated database for each testcase](https://github.com/xorcare/testing-go-code-with-postgres/blob/main/user_repository_with_isolated_database_test.go). - And example of [GitHub Actions](https://github.com/xorcare/testing-go-code-with-postgres/blob/main/.github/workflows/go.yml) and [Gitlab CI](https://github.com/xorcare/testing-go-code-with-postgres/blob/main/.gitlab-ci.yml). diff --git a/testingpg/testingpg.go b/testingpg/testingpg.go index 9e6319b..862591f 100644 --- a/testingpg/testingpg.go +++ b/testingpg/testingpg.go @@ -31,7 +31,7 @@ type TestingT interface { Failed() bool } -func New(t TestingT) *Postgres { +func NewWithIsolatedDatabase(t TestingT) *Postgres { return newPostgres(t).cloneFromReference() } diff --git a/testingpg/testingpg_test.go b/testingpg/testingpg_test.go index 48e417b..5d0b413 100644 --- a/testingpg/testingpg_test.go +++ b/testingpg/testingpg_test.go @@ -25,7 +25,7 @@ func TestNewPostgres(t *testing.T) { t.Parallel() // Arrange - postgres := testingpg.New(t) + postgres := testingpg.NewWithIsolatedDatabase(t) ctx := context.Background() dbPool, err := pgxpool.New(ctx, postgres.URL()) @@ -45,7 +45,7 @@ func TestNewPostgres(t *testing.T) { t.Parallel() // Arrange - postgres := testingpg.New(t) + postgres := testingpg.NewWithIsolatedDatabase(t) ctx := context.Background() // Act @@ -63,8 +63,8 @@ func TestNewPostgres(t *testing.T) { t.Parallel() // Arrange - postgres1 := testingpg.New(t) - postgres2 := testingpg.New(t) + postgres1 := testingpg.NewWithIsolatedDatabase(t) + postgres2 := testingpg.NewWithIsolatedDatabase(t) ctx := context.Background() @@ -82,8 +82,8 @@ func TestNewPostgres(t *testing.T) { t.Parallel() // Arrange - postgres1 := testingpg.New(t) - postgres2 := testingpg.New(t) + postgres1 := testingpg.NewWithIsolatedDatabase(t) + postgres2 := testingpg.NewWithIsolatedDatabase(t) // Act url1 := postgres1.URL() diff --git a/user_repository_test.go b/user_repository_test.go index 4612b2f..77acb19 100644 --- a/user_repository_test.go +++ b/user_repository_test.go @@ -4,93 +4,7 @@ package testing_go_code_with_postgres_test -import ( - "context" - "testing" - "time" - - "github.com/google/uuid" - "github.com/stretchr/testify/require" - - rootpkg "github.com/xorcare/testing-go-code-with-postgres" - "github.com/xorcare/testing-go-code-with-postgres/testingpg" -) - -func TestUserRepository_CreateUser(t *testing.T) { - if testing.Short() { - t.Skip("skipping test in short mode") - } - - t.Parallel() - - newFullyFiledUser := func() rootpkg.User { - return rootpkg.User{ - ID: uuid.New(), - Username: "gopher", - CreatedAt: time.Now().Truncate(time.Microsecond), - } - } - - t.Run("Successfully created a User", func(t *testing.T) { - t.Parallel() - - // Arrange - postgres := testingpg.New(t) - repo := rootpkg.NewUserRepository(postgres.DB()) - - user := newFullyFiledUser() - - // Act - err := repo.CreateUser(context.Background(), user) - - // Assert - require.NoError(t, err) - - gotUser, err := repo.ReadUser(context.Background(), user.ID) - require.NoError(t, err) - - require.Equal(t, user, gotUser) - }) - - t.Run("Cannot create a user with the same ID", func(t *testing.T) { - t.Parallel() - - // Arrange - postgres := testingpg.New(t) - repo := rootpkg.NewUserRepository(postgres.DB()) - - user := newFullyFiledUser() - - err := repo.CreateUser(context.Background(), user) - require.NoError(t, err) - - // Act - err = repo.CreateUser(context.Background(), user) - - // Assert - require.Error(t, err) - require.Contains(t, err.Error(), "duplicate key value violates unique constraint") - }) -} - -func TestUserRepository_ReadUser(t *testing.T) { - if testing.Short() { - t.Skip("skipping test in short mode") - } - - t.Parallel() - - t.Run("Get an error if the user does not exist", func(t *testing.T) { - t.Parallel() - - // Arrange - postgres := testingpg.New(t) - repo := rootpkg.NewUserRepository(postgres.DB()) - - // Act - _, err := repo.ReadUser(context.Background(), uuid.New()) - - // Assert - require.Error(t, err) - }) -} +// Since the repository contains examples of different approaches to +// database cleanup, this file is empty. The specific tests can be found +// in the following files: +// - user_repository_with_isolated_database_test.go diff --git a/user_repository_with_isolated_database_test.go b/user_repository_with_isolated_database_test.go new file mode 100644 index 0000000..bdad927 --- /dev/null +++ b/user_repository_with_isolated_database_test.go @@ -0,0 +1,96 @@ +// Copyright (c) 2023 Vasiliy Vasilyuk. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testing_go_code_with_postgres_test + +import ( + "context" + "testing" + "time" + + "github.com/google/uuid" + "github.com/stretchr/testify/require" + + rootpkg "github.com/xorcare/testing-go-code-with-postgres" + "github.com/xorcare/testing-go-code-with-postgres/testingpg" +) + +func TestUserRepository_CreateUser(t *testing.T) { + if testing.Short() { + t.Skip("skipping test in short mode") + } + + t.Parallel() + + newFullyFiledUser := func() rootpkg.User { + return rootpkg.User{ + ID: uuid.New(), + Username: "gopher", + CreatedAt: time.Now().Truncate(time.Microsecond), + } + } + + t.Run("Successfully created a User", func(t *testing.T) { + t.Parallel() + + // Arrange + postgres := testingpg.NewWithIsolatedDatabase(t) + repo := rootpkg.NewUserRepository(postgres.DB()) + + user := newFullyFiledUser() + + // Act + err := repo.CreateUser(context.Background(), user) + + // Assert + require.NoError(t, err) + + gotUser, err := repo.ReadUser(context.Background(), user.ID) + require.NoError(t, err) + + require.Equal(t, user, gotUser) + }) + + t.Run("Cannot create a user with the same ID", func(t *testing.T) { + t.Parallel() + + // Arrange + postgres := testingpg.NewWithIsolatedDatabase(t) + repo := rootpkg.NewUserRepository(postgres.DB()) + + user := newFullyFiledUser() + + err := repo.CreateUser(context.Background(), user) + require.NoError(t, err) + + // Act + err = repo.CreateUser(context.Background(), user) + + // Assert + require.Error(t, err) + require.Contains(t, err.Error(), "duplicate key value violates unique constraint") + }) +} + +func TestUserRepository_ReadUser(t *testing.T) { + if testing.Short() { + t.Skip("skipping test in short mode") + } + + t.Parallel() + + t.Run("Get an error if the user does not exist", func(t *testing.T) { + t.Parallel() + + // Arrange + postgres := testingpg.NewWithIsolatedDatabase(t) + repo := rootpkg.NewUserRepository(postgres.DB()) + + // Act + _, err := repo.ReadUser(context.Background(), uuid.New()) + + // Assert + require.Error(t, err) + }) +}