ms-auth/internal/users/repository/pg_repository_test.go
2024-10-13 22:45:39 +05:00

202 lines
4.5 KiB
Go

package repository
import (
"context"
"database/sql/driver"
"git.sch9.ru/new_gate/ms-auth/pkg/utils"
"github.com/DATA-DOG/go-sqlmock"
"github.com/jmoiron/sqlx"
"github.com/stretchr/testify/require"
"go.uber.org/zap"
"testing"
"time"
"git.sch9.ru/new_gate/ms-auth/internal/models"
)
func TestUsersRepository_CreateUser(t *testing.T) {
t.Parallel()
db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
require.NoError(t, err)
defer db.Close()
sqlxDB := sqlx.NewDb(db, "sqlmock")
defer sqlxDB.Close()
userRepo := NewUserRepository(sqlxDB, zap.NewNop())
t.Run("valid user creation", func(t *testing.T) {
rows := sqlmock.NewRows([]string{"id"}).AddRow(1)
user := &models.User{
Username: utils.AsStringP("testuser"),
Password: utils.AsStringP("testpassword"),
Email: utils.AsStringP("test@example.com"),
Role: AsRoleP(models.RoleAdmin),
}
mock.ExpectQuery(sqlxDB.Rebind(createUser)).WithArgs(
user.Username,
AnyString{},
user.Email,
AnyTime{},
user.Role,
).WillReturnRows(rows)
_, err = userRepo.CreateUser(context.Background(), user)
require.NoError(t, err)
})
// TODO: add more tests
// invalid username
// invalid password
// invalid email
// invalid role
// password hashing error
// database query error
// database scan error
// etc
}
func TestUsersRepository_ReadUserById(t *testing.T) {
t.Parallel()
db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
require.NoError(t, err)
defer db.Close()
sqlxDB := sqlx.NewDb(db, "sqlmock")
defer sqlxDB.Close()
userRepo := NewUserRepository(sqlxDB, zap.NewNop())
t.Run("valid user read", func(t *testing.T) {
user := &models.User{
Id: utils.AsInt32P(1),
Username: utils.AsStringP("testuser"),
Password: utils.AsStringP("testpassword"),
Email: utils.AsStringP("test@example.com"),
ExpiresAt: utils.AsTimeP(time.Now().Add(1 * time.Hour)),
CreatedAt: utils.AsTimeP(time.Now()),
UpdatedAt: utils.AsTimeP(time.Now()),
Role: AsRoleP(models.RoleAdmin),
}
rows := sqlmock.NewRows(
[]string{
"id",
"username",
"hashed_pwd",
"email",
"expires_at",
"created_at",
"updated_at",
"role",
}).AddRow(
*user.Id,
*user.Username,
*user.Password,
*user.Email,
*user.ExpiresAt,
*user.CreatedAt,
*user.UpdatedAt,
*user.Role,
)
mock.ExpectQuery(sqlxDB.Rebind(readUserById)).WithArgs(
*user.Id,
).WillReturnRows(rows)
readUser, err := userRepo.ReadUserById(context.Background(), *user.Id)
require.NoError(t, err)
require.Equal(t, user, readUser)
})
}
func TestUsersRepository_UpdateUser(t *testing.T) {
t.Parallel()
db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
require.NoError(t, err)
defer db.Close()
sqlxDB := sqlx.NewDb(db, "sqlmock")
defer sqlxDB.Close()
userRepo := NewUserRepository(sqlxDB, zap.NewNop())
t.Run("valid user update", func(t *testing.T) {
user := &models.User{
Id: utils.AsInt32P(1),
Username: utils.AsStringP("testuser"),
Password: utils.AsStringP("testpassword"),
Email: utils.AsStringP("test@example.com"),
ExpiresAt: utils.AsTimeP(time.Now().Add(1 * time.Hour)),
Role: AsRoleP(models.RoleAdmin),
}
require.NoError(t, err)
mock.ExpectExec(sqlxDB.Rebind(updateUser)).
WithArgs(
*user.Username,
AnyString{},
*user.Email,
*user.ExpiresAt,
*user.Role,
*user.Id,
).WillReturnResult(sqlmock.NewResult(1, 1))
err = userRepo.UpdateUser(context.Background(), user)
require.NoError(t, err)
})
// TODO: add more tests
}
func TestUsersRepository_DeleteUser(t *testing.T) {
t.Parallel()
db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
require.NoError(t, err)
defer db.Close()
sqlxDB := sqlx.NewDb(db, "sqlmock")
defer sqlxDB.Close()
userRepo := NewUserRepository(sqlxDB, zap.NewNop())
t.Run("valid user deletion", func(t *testing.T) {
user := &models.User{
Id: utils.AsInt32P(1),
}
mock.ExpectExec(sqlxDB.Rebind(deleteUser)).WithArgs(*user.Id).WillReturnResult(sqlmock.NewResult(1, 1))
err = userRepo.DeleteUser(context.Background(), *user.Id)
require.NoError(t, err)
})
// TODO: add more tests
}
func AsRoleP(r models.Role) *models.Role {
return &r
}
type AnyTime struct{}
// Match satisfies sqlmock.Argument interface
func (a AnyTime) Match(v driver.Value) bool {
_, ok := v.(time.Time)
return ok
}
type AnyString struct{}
func (a AnyString) Match(v driver.Value) bool {
_, ok := v.(string)
return ok
}