2024-10-09 17:07:38 +00:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2024-10-13 17:45:39 +00:00
|
|
|
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)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2024-10-09 17:07:38 +00:00
|
|
|
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
|
|
|
|
}
|