test: added two variants of tests for user repository
This commit is contained in:
@@ -3,6 +3,7 @@ module github.com/robindittmar/dttmr-api
|
|||||||
go 1.26
|
go 1.26
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/DATA-DOG/go-sqlmock v1.5.2
|
||||||
github.com/golang-jwt/jwt/v5 v5.3.1
|
github.com/golang-jwt/jwt/v5 v5.3.1
|
||||||
github.com/golang-migrate/migrate/v4 v4.19.1
|
github.com/golang-migrate/migrate/v4 v4.19.1
|
||||||
github.com/jackc/pgx/v5 v5.10.0
|
github.com/jackc/pgx/v5 v5.10.0
|
||||||
|
|||||||
@@ -0,0 +1,189 @@
|
|||||||
|
package repository
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"regexp"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/DATA-DOG/go-sqlmock"
|
||||||
|
"github.com/robindittmar/dttmr-api/internal/domain"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestUserRepo_CreateUser(t *testing.T) {
|
||||||
|
db, mock, err := sqlmock.New()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
defer db.Close()
|
||||||
|
|
||||||
|
repo := NewUserRepo(db)
|
||||||
|
|
||||||
|
ctx := context.Background()
|
||||||
|
email := "test@example.com"
|
||||||
|
name := "Test User"
|
||||||
|
passwordHash := "hashedpassword123"
|
||||||
|
|
||||||
|
now := time.Now()
|
||||||
|
expectedUser := &domain.User{
|
||||||
|
ID: "1",
|
||||||
|
Email: email,
|
||||||
|
Name: name,
|
||||||
|
CreatedAt: now,
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Run("success", func(t *testing.T) {
|
||||||
|
mock.ExpectBegin()
|
||||||
|
|
||||||
|
mock.ExpectQuery(`^INSERT INTO users \(email, name, password_hash\) VALUES \(\$1, \$2, \$3\) RETURNING id, created_at$`).
|
||||||
|
WithArgs(email, name, passwordHash).
|
||||||
|
WillReturnRows(sqlmock.NewRows([]string{"id", "created_at"}).AddRow(expectedUser.ID, expectedUser.CreatedAt))
|
||||||
|
|
||||||
|
mock.ExpectCommit()
|
||||||
|
|
||||||
|
user, err := repo.CreateUser(ctx, email, name, passwordHash)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, expectedUser, user)
|
||||||
|
assert.NoError(t, mock.ExpectationsWereMet())
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("begin_tx_error", func(t *testing.T) {
|
||||||
|
mock.ExpectBegin().WillReturnError(fmt.Errorf("tx error"))
|
||||||
|
|
||||||
|
user, err := repo.CreateUser(ctx, email, name, passwordHash)
|
||||||
|
assert.Error(t, err)
|
||||||
|
assert.Contains(t, err.Error(), "begin transaction")
|
||||||
|
assert.Nil(t, user)
|
||||||
|
assert.NoError(t, mock.ExpectationsWereMet())
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("insert_error", func(t *testing.T) {
|
||||||
|
mock.ExpectBegin()
|
||||||
|
mock.ExpectQuery(`^INSERT INTO users \(email, name, password_hash\) VALUES \(\$1, \$2, \$3\) RETURNING id, created_at$`).
|
||||||
|
WithArgs(email, name, passwordHash).
|
||||||
|
WillReturnError(fmt.Errorf("insert error"))
|
||||||
|
mock.ExpectRollback()
|
||||||
|
|
||||||
|
user, err := repo.CreateUser(ctx, email, name, passwordHash)
|
||||||
|
assert.Error(t, err)
|
||||||
|
assert.Contains(t, err.Error(), "failed to insert user")
|
||||||
|
assert.Nil(t, user)
|
||||||
|
assert.NoError(t, mock.ExpectationsWereMet())
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("commit_error", func(t *testing.T) {
|
||||||
|
mock.ExpectBegin()
|
||||||
|
mock.ExpectQuery(`^INSERT INTO users \(email, name, password_hash\) VALUES \(\$1, \$2, \$3\) RETURNING id, created_at$`).
|
||||||
|
WithArgs(email, name, passwordHash).
|
||||||
|
WillReturnRows(sqlmock.NewRows([]string{"id", "created_at"}).AddRow(expectedUser.ID, expectedUser.CreatedAt))
|
||||||
|
mock.ExpectCommit().WillReturnError(fmt.Errorf("commit error"))
|
||||||
|
|
||||||
|
user, err := repo.CreateUser(ctx, email, name, passwordHash)
|
||||||
|
assert.Error(t, err)
|
||||||
|
assert.Contains(t, err.Error(), "commit transaction")
|
||||||
|
assert.Nil(t, user)
|
||||||
|
assert.NoError(t, mock.ExpectationsWereMet())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUserRepo_CreateUser2(t *testing.T) {
|
||||||
|
email := "test@example.com"
|
||||||
|
name := "Test User"
|
||||||
|
passwordHash := "hashedpassword123"
|
||||||
|
now := time.Now()
|
||||||
|
expectedID := "42"
|
||||||
|
|
||||||
|
insertQuery := regexp.QuoteMeta(
|
||||||
|
"INSERT INTO users (email, name, password_hash) VALUES ($1, $2, $3) RETURNING id, created_at",
|
||||||
|
)
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
setupMock func(mock sqlmock.Sqlmock)
|
||||||
|
expectedError string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Success: User created perfectly",
|
||||||
|
setupMock: func(mock sqlmock.Sqlmock) {
|
||||||
|
mock.ExpectBegin()
|
||||||
|
|
||||||
|
rows := sqlmock.NewRows([]string{"id", "created_at"}).
|
||||||
|
AddRow(expectedID, now)
|
||||||
|
|
||||||
|
mock.ExpectQuery(insertQuery).
|
||||||
|
WithArgs(email, name, passwordHash).
|
||||||
|
WillReturnRows(rows)
|
||||||
|
|
||||||
|
mock.ExpectCommit()
|
||||||
|
},
|
||||||
|
expectedError: "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Failure: Database connection fails on BeginTx",
|
||||||
|
setupMock: func(mock sqlmock.Sqlmock) {
|
||||||
|
mock.ExpectBegin().WillReturnError(errors.New("db connection failed"))
|
||||||
|
},
|
||||||
|
expectedError: "begin transaction: db connection failed",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Failure: Query fails (e.g., duplicate email)",
|
||||||
|
setupMock: func(mock sqlmock.Sqlmock) {
|
||||||
|
mock.ExpectBegin()
|
||||||
|
|
||||||
|
mock.ExpectQuery(insertQuery).
|
||||||
|
WithArgs(email, name, passwordHash).
|
||||||
|
WillReturnError(errors.New("unique constraint violation"))
|
||||||
|
|
||||||
|
mock.ExpectRollback()
|
||||||
|
},
|
||||||
|
expectedError: "failed to insert user: unique constraint violation",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Failure: Commit fails (e.g., network timeout)",
|
||||||
|
setupMock: func(mock sqlmock.Sqlmock) {
|
||||||
|
mock.ExpectBegin()
|
||||||
|
|
||||||
|
rows := sqlmock.NewRows([]string{"id", "created_at"}).
|
||||||
|
AddRow(expectedID, now)
|
||||||
|
|
||||||
|
mock.ExpectQuery(insertQuery).
|
||||||
|
WithArgs(email, name, passwordHash).
|
||||||
|
WillReturnRows(rows)
|
||||||
|
|
||||||
|
mock.ExpectCommit().WillReturnError(errors.New("commit timeout"))
|
||||||
|
},
|
||||||
|
expectedError: "commit transaction: commit timeout",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
db, mock, err := sqlmock.New()
|
||||||
|
require.NoError(t, err)
|
||||||
|
defer db.Close()
|
||||||
|
|
||||||
|
tc.setupMock(mock)
|
||||||
|
|
||||||
|
repo := NewUserRepo(db)
|
||||||
|
|
||||||
|
user, err := repo.CreateUser(context.Background(), email, name, passwordHash)
|
||||||
|
|
||||||
|
if tc.expectedError != "" {
|
||||||
|
require.Error(t, err)
|
||||||
|
assert.Contains(t, err.Error(), tc.expectedError)
|
||||||
|
assert.Nil(t, user)
|
||||||
|
} else {
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, user)
|
||||||
|
assert.Equal(t, expectedID, user.ID)
|
||||||
|
assert.Equal(t, email, user.Email)
|
||||||
|
assert.Equal(t, name, user.Name)
|
||||||
|
assert.Equal(t, now, user.CreatedAt)
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.NoError(t, mock.ExpectationsWereMet())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user