462 lines
16 KiB
Go
462 lines
16 KiB
Go
package service
|
|
|
|
import (
|
|
"encoding"
|
|
"errors"
|
|
"github.com/stretchr/testify/assert"
|
|
"go.uber.org/mock/gomock"
|
|
"testing"
|
|
"time"
|
|
|
|
"git.urec56.ru/urec/chat_back_go/config"
|
|
"git.urec56.ru/urec/chat_back_go/internal/domain"
|
|
"git.urec56.ru/urec/chat_back_go/internal/logger"
|
|
mock_repository "git.urec56.ru/urec/chat_back_go/internal/repository/mocks"
|
|
mock_service "git.urec56.ru/urec/chat_back_go/internal/service/mocks"
|
|
)
|
|
|
|
func Test_newUserService(t *testing.T) {
|
|
c := gomock.NewController(t)
|
|
defer c.Finish()
|
|
|
|
repo := mock_repository.NewMockUser(c)
|
|
auth := mock_service.NewMockAuth(c)
|
|
log := logger.NewLogger(config.Config{Mode: "TEST"})
|
|
cache := mock_service.NewMockCache(c)
|
|
|
|
serv := newUserService(repo, auth, log, cache)
|
|
|
|
assert.EqualValues(t, &userService{ur: repo, auth: auth, l: log, cache: cache}, serv)
|
|
}
|
|
|
|
func TestUserService_Get(t *testing.T) {
|
|
type repoBehavior func(r *mock_repository.MockUser, userID int, user domain.User, err error)
|
|
type cacheGetBehavior func(c *mock_service.MockCache, key string, v encoding.BinaryUnmarshaler, err error)
|
|
type cacheSetBehavior func(c *mock_service.MockCache, key string, v encoding.BinaryMarshaler, ex time.Duration, err error)
|
|
type cacheGetData struct {
|
|
container *domain.User
|
|
err error
|
|
}
|
|
type cacheSetData struct {
|
|
value domain.User
|
|
duration time.Duration
|
|
err error
|
|
}
|
|
|
|
testTable := []struct {
|
|
name string
|
|
repoBehavior repoBehavior
|
|
cacheGetBehavior cacheGetBehavior
|
|
cacheSetBehavior cacheSetBehavior
|
|
cacheKey string
|
|
cacheGetData cacheGetData
|
|
cacheSetData cacheSetData
|
|
userID int
|
|
repoUser domain.User
|
|
repoErr error
|
|
logErr1 error
|
|
logErr2 error
|
|
expectedUser domain.User
|
|
expectedErr error
|
|
}{
|
|
{
|
|
name: "user_in_cache",
|
|
repoBehavior: func(r *mock_repository.MockUser, userID int, user domain.User, err error) {},
|
|
cacheGetBehavior: func(c *mock_service.MockCache, key string, v encoding.BinaryUnmarshaler, err error) {
|
|
c.EXPECT().Get(key, gomock.Any(), false).DoAndReturn(
|
|
func(key string, v encoding.BinaryUnmarshaler, isFast bool) error {
|
|
return v.UnmarshalBinary([]byte(`{"id": 1}`))
|
|
},
|
|
)
|
|
},
|
|
cacheSetBehavior: func(c *mock_service.MockCache, key string, v encoding.BinaryMarshaler, ex time.Duration, err error) {},
|
|
cacheKey: "user: {'id': 1}",
|
|
cacheGetData: cacheGetData{container: &domain.User{}},
|
|
userID: 1,
|
|
expectedUser: domain.User{ID: 1},
|
|
},
|
|
{
|
|
name: "no_user_in_cache",
|
|
repoBehavior: func(r *mock_repository.MockUser, userID int, user domain.User, err error) {
|
|
r.EXPECT().GetByID(userID).Return(user, err)
|
|
},
|
|
cacheGetBehavior: func(c *mock_service.MockCache, key string, v encoding.BinaryUnmarshaler, err error) {
|
|
c.EXPECT().Get(key, gomock.Any(), false).Return(err)
|
|
},
|
|
cacheSetBehavior: func(c *mock_service.MockCache, key string, v encoding.BinaryMarshaler, ex time.Duration, err error) {
|
|
c.EXPECT().Set(key, v, ex).Return(err)
|
|
},
|
|
cacheKey: "user: {'id': 1}",
|
|
cacheGetData: cacheGetData{container: &domain.User{}, err: domain.NoKeyFoundError},
|
|
cacheSetData: cacheSetData{value: domain.User{ID: 1}, duration: time.Second * 20},
|
|
logErr1: domain.NoKeyFoundError,
|
|
userID: 1,
|
|
repoUser: domain.User{ID: 1},
|
|
expectedUser: domain.User{ID: 1},
|
|
},
|
|
{
|
|
name: "user_not_found",
|
|
repoBehavior: func(r *mock_repository.MockUser, userID int, user domain.User, err error) {
|
|
r.EXPECT().GetByID(userID).Return(user, err)
|
|
},
|
|
cacheGetBehavior: func(c *mock_service.MockCache, key string, v encoding.BinaryUnmarshaler, err error) {
|
|
c.EXPECT().Get(key, gomock.Any(), false).Return(err)
|
|
},
|
|
cacheSetBehavior: func(c *mock_service.MockCache, key string, v encoding.BinaryMarshaler, ex time.Duration, err error) {},
|
|
cacheKey: "user: {'id': 1}",
|
|
cacheGetData: cacheGetData{container: &domain.User{}, err: domain.NoKeyFoundError},
|
|
logErr1: domain.NoKeyFoundError,
|
|
userID: 1,
|
|
repoErr: domain.UserNotFoundError,
|
|
expectedErr: domain.UserNotFoundError,
|
|
},
|
|
{
|
|
name: "cache_get_error",
|
|
repoBehavior: func(r *mock_repository.MockUser, userID int, user domain.User, err error) {
|
|
r.EXPECT().GetByID(userID).Return(user, err)
|
|
},
|
|
cacheGetBehavior: func(c *mock_service.MockCache, key string, v encoding.BinaryUnmarshaler, err error) {
|
|
c.EXPECT().Get(key, gomock.Any(), false).Return(err)
|
|
},
|
|
cacheSetBehavior: func(c *mock_service.MockCache, key string, v encoding.BinaryMarshaler, ex time.Duration, err error) {
|
|
c.EXPECT().Set(key, v, ex).Return(err)
|
|
},
|
|
cacheKey: "user: {'id': 1}",
|
|
cacheGetData: cacheGetData{container: &domain.User{}, err: domain.InternalServerError},
|
|
cacheSetData: cacheSetData{value: domain.User{ID: 1}, duration: time.Second * 20},
|
|
logErr1: domain.InternalServerError,
|
|
userID: 1,
|
|
repoUser: domain.User{ID: 1},
|
|
expectedUser: domain.User{ID: 1},
|
|
},
|
|
{
|
|
name: "cache_set_error",
|
|
repoBehavior: func(r *mock_repository.MockUser, userID int, user domain.User, err error) {
|
|
r.EXPECT().GetByID(userID).Return(user, err)
|
|
},
|
|
cacheGetBehavior: func(c *mock_service.MockCache, key string, v encoding.BinaryUnmarshaler, err error) {
|
|
c.EXPECT().Get(key, gomock.Any(), false).Return(err)
|
|
},
|
|
cacheSetBehavior: func(c *mock_service.MockCache, key string, v encoding.BinaryMarshaler, ex time.Duration, err error) {
|
|
c.EXPECT().Set(key, v, ex).Return(err)
|
|
},
|
|
cacheKey: "user: {'id': 1}",
|
|
cacheGetData: cacheGetData{container: &domain.User{}, err: domain.NoKeyFoundError},
|
|
cacheSetData: cacheSetData{value: domain.User{ID: 1}, duration: time.Second * 20, err: domain.InternalServerError},
|
|
logErr1: domain.NoKeyFoundError,
|
|
logErr2: domain.InternalServerError,
|
|
userID: 1,
|
|
repoUser: domain.User{ID: 1},
|
|
expectedUser: domain.User{ID: 1},
|
|
},
|
|
{
|
|
name: "repo_error",
|
|
repoBehavior: func(r *mock_repository.MockUser, userID int, user domain.User, err error) {
|
|
r.EXPECT().GetByID(userID).Return(user, err)
|
|
},
|
|
cacheGetBehavior: func(c *mock_service.MockCache, key string, v encoding.BinaryUnmarshaler, err error) {
|
|
c.EXPECT().Get(key, gomock.Any(), false).Return(err)
|
|
},
|
|
cacheSetBehavior: func(c *mock_service.MockCache, key string, v encoding.BinaryMarshaler, ex time.Duration, err error) {},
|
|
cacheKey: "user: {'id': 1}",
|
|
cacheGetData: cacheGetData{container: &domain.User{}, err: domain.NoKeyFoundError},
|
|
logErr1: domain.NoKeyFoundError,
|
|
userID: 1,
|
|
repoErr: domain.InternalServerError,
|
|
expectedErr: domain.InternalServerError,
|
|
},
|
|
}
|
|
|
|
for _, tc := range testTable {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
c := gomock.NewController(t)
|
|
defer c.Finish()
|
|
|
|
repo := mock_repository.NewMockUser(c)
|
|
cache := mock_service.NewMockCache(c)
|
|
log := logger.NewLogger(config.Config{Mode: "TEST"})
|
|
serv := userService{ur: repo, l: log, cache: cache}
|
|
|
|
tc.repoBehavior(repo, tc.userID, tc.repoUser, tc.repoErr)
|
|
tc.cacheGetBehavior(cache, tc.cacheKey, tc.cacheGetData.container, tc.cacheGetData.err)
|
|
tc.cacheSetBehavior(cache, tc.cacheKey, &tc.cacheSetData.value, tc.cacheSetData.duration, tc.cacheSetData.err)
|
|
|
|
u, err := serv.Get(tc.userID, false)
|
|
|
|
assert.Equal(t, tc.expectedUser, u)
|
|
assert.ErrorIs(t, err, tc.expectedErr)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestUserService_GetVerificated(t *testing.T) {
|
|
type mockBehavior func(r *mock_repository.MockUser, userID int, user domain.User, err error)
|
|
|
|
testTable := []struct {
|
|
name string
|
|
mockBehavior mockBehavior
|
|
userID int
|
|
expectedUser domain.User
|
|
repoErr error
|
|
expectedErr error
|
|
}{
|
|
{
|
|
name: "ok",
|
|
mockBehavior: func(r *mock_repository.MockUser, userID int, user domain.User, err error) {
|
|
r.EXPECT().GetByID(userID).Return(user, err)
|
|
},
|
|
userID: 1,
|
|
expectedUser: domain.User{
|
|
ID: 1,
|
|
Role: domain.VerificatedUser,
|
|
},
|
|
},
|
|
{
|
|
name: "user_not_found",
|
|
mockBehavior: func(r *mock_repository.MockUser, userID int, user domain.User, err error) {
|
|
r.EXPECT().GetByID(userID).Return(user, err)
|
|
},
|
|
userID: 1,
|
|
repoErr: domain.UserNotFoundError,
|
|
expectedErr: domain.UserNotFoundError,
|
|
},
|
|
{
|
|
name: "user_unverified",
|
|
mockBehavior: func(r *mock_repository.MockUser, userID int, user domain.User, err error) {
|
|
r.EXPECT().GetByID(userID).Return(user, err)
|
|
},
|
|
userID: 1,
|
|
expectedUser: domain.User{
|
|
ID: 1,
|
|
Role: domain.UnverifiedUser,
|
|
},
|
|
expectedErr: domain.UnverifiedUserError,
|
|
},
|
|
}
|
|
|
|
for _, tc := range testTable {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
c := gomock.NewController(t)
|
|
defer c.Finish()
|
|
|
|
repo := mock_repository.NewMockUser(c)
|
|
serv := userService{ur: repo}
|
|
|
|
tc.mockBehavior(repo, tc.userID, tc.expectedUser, tc.repoErr)
|
|
|
|
u, err := serv.GetVerificated(tc.userID)
|
|
|
|
assert.Equal(t, tc.expectedUser, u)
|
|
assert.ErrorIs(t, err, tc.expectedErr)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestUserService_GetAll(t *testing.T) {
|
|
type mockBehavior func(r *mock_repository.MockUser, username string, users []domain.User, err error)
|
|
|
|
testTable := []struct {
|
|
name string
|
|
mockBehavior mockBehavior
|
|
username string
|
|
expectedUsers []domain.User
|
|
repoErr error
|
|
expectedErr error
|
|
}{
|
|
{
|
|
name: "ok",
|
|
mockBehavior: func(r *mock_repository.MockUser, username string, users []domain.User, err error) {
|
|
r.EXPECT().GetAll(username).Return(users, err)
|
|
},
|
|
expectedUsers: []domain.User{
|
|
{ID: 1},
|
|
},
|
|
},
|
|
{
|
|
name: "internal_error",
|
|
mockBehavior: func(r *mock_repository.MockUser, username string, users []domain.User, err error) {
|
|
r.EXPECT().GetAll(username).Return(users, err)
|
|
},
|
|
repoErr: domain.InternalServerError,
|
|
expectedErr: domain.InternalServerError,
|
|
},
|
|
}
|
|
|
|
for _, tc := range testTable {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
c := gomock.NewController(t)
|
|
defer c.Finish()
|
|
|
|
repo := mock_repository.NewMockUser(c)
|
|
serv := userService{ur: repo}
|
|
|
|
tc.mockBehavior(repo, tc.username, tc.expectedUsers, tc.repoErr)
|
|
|
|
u, err := serv.GetAll(tc.username)
|
|
|
|
assert.Equal(t, tc.expectedUsers, u)
|
|
assert.ErrorIs(t, err, tc.expectedErr)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestUserService_FindOne(t *testing.T) {
|
|
type mockBehavior func(r *mock_repository.MockUser, username, email string, user domain.User, err error)
|
|
|
|
testTable := []struct {
|
|
name string
|
|
mockBehavior mockBehavior
|
|
username string
|
|
email string
|
|
expectedUser domain.User
|
|
repoErr error
|
|
expectedErr error
|
|
}{
|
|
{
|
|
name: "ok",
|
|
mockBehavior: func(r *mock_repository.MockUser, username, email string, user domain.User, err error) {
|
|
r.EXPECT().FindOne(username, email).Return(user, err)
|
|
},
|
|
expectedUser: domain.User{
|
|
ID: 1,
|
|
Role: domain.UnverifiedUser,
|
|
},
|
|
},
|
|
{
|
|
name: "any_error",
|
|
mockBehavior: func(r *mock_repository.MockUser, username, email string, user domain.User, err error) {
|
|
r.EXPECT().FindOne(username, email).Return(user, err)
|
|
},
|
|
repoErr: errors.New("some error"),
|
|
expectedErr: domain.InternalServerError,
|
|
},
|
|
}
|
|
|
|
for _, tc := range testTable {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
c := gomock.NewController(t)
|
|
defer c.Finish()
|
|
|
|
repo := mock_repository.NewMockUser(c)
|
|
serv := userService{ur: repo}
|
|
|
|
tc.mockBehavior(repo, tc.username, tc.email, tc.expectedUser, tc.repoErr)
|
|
|
|
u, err := serv.FindOne(tc.username, tc.email)
|
|
|
|
assert.Equal(t, tc.expectedUser, u)
|
|
assert.ErrorIs(t, err, tc.expectedErr)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestUserService_Register(t *testing.T) {
|
|
type hashMockBehavior func(s *mock_service.MockAuth, p, hp string, err error)
|
|
type repoMockBehavior func(r *mock_repository.MockUser, email, hp, username string, dateOfBirth time.Time, user domain.User, err error)
|
|
type encodeMockBehavior func(s *mock_service.MockAuth, userID int, token string, err error)
|
|
|
|
testTable := []struct {
|
|
name string
|
|
hashMockBehavior hashMockBehavior
|
|
repoMockBehavior repoMockBehavior
|
|
encodeMockBehavior encodeMockBehavior
|
|
ud domain.UserRegister
|
|
hp string
|
|
repoUser domain.User
|
|
hashErr error
|
|
repoErr error
|
|
encodeErr error
|
|
expectedToken string
|
|
expectedErr error
|
|
}{
|
|
{
|
|
name: "ok",
|
|
hashMockBehavior: func(s *mock_service.MockAuth, p, hp string, err error) {
|
|
s.EXPECT().HashPassword(p).Return(hp, err)
|
|
},
|
|
repoMockBehavior: func(r *mock_repository.MockUser, email, hp, username string, dateOfBirth time.Time, user domain.User, err error) {
|
|
r.EXPECT().Register(email, hp, username, dateOfBirth).Return(user, err)
|
|
},
|
|
encodeMockBehavior: func(s *mock_service.MockAuth, userID int, token string, err error) {
|
|
s.EXPECT().EncodeAuthToken(userID).Return(token, err)
|
|
},
|
|
ud: domain.UserRegister{
|
|
Email: "mail@mail.ru",
|
|
Username: "username",
|
|
Password: "pass",
|
|
},
|
|
hp: "hp",
|
|
repoUser: domain.User{ID: 1},
|
|
expectedToken: "token",
|
|
},
|
|
{
|
|
name: "user_already_exists",
|
|
hashMockBehavior: func(s *mock_service.MockAuth, p, hp string, err error) {
|
|
s.EXPECT().HashPassword(p).Return(hp, err)
|
|
},
|
|
repoMockBehavior: func(r *mock_repository.MockUser, email, hp, username string, dateOfBirth time.Time, user domain.User, err error) {
|
|
r.EXPECT().Register(email, hp, username, dateOfBirth).Return(user, err)
|
|
},
|
|
encodeMockBehavior: func(s *mock_service.MockAuth, userID int, token string, err error) {},
|
|
repoErr: domain.UserAlreadyExistsError,
|
|
expectedErr: domain.UserAlreadyExistsError,
|
|
},
|
|
{
|
|
name: "hash_failed",
|
|
hashMockBehavior: func(s *mock_service.MockAuth, p, hp string, err error) {
|
|
s.EXPECT().HashPassword(p).Return(hp, err)
|
|
},
|
|
repoMockBehavior: func(r *mock_repository.MockUser, email, hp, username string, dateOfBirth time.Time, user domain.User, err error) {
|
|
},
|
|
encodeMockBehavior: func(s *mock_service.MockAuth, userID int, token string, err error) {},
|
|
hashErr: errors.New("some error"),
|
|
expectedErr: domain.InternalServerError,
|
|
},
|
|
{
|
|
name: "db_error",
|
|
hashMockBehavior: func(s *mock_service.MockAuth, p, hp string, err error) {
|
|
s.EXPECT().HashPassword(p).Return(hp, err)
|
|
},
|
|
repoMockBehavior: func(r *mock_repository.MockUser, email, hp, username string, dateOfBirth time.Time, user domain.User, err error) {
|
|
r.EXPECT().Register(email, hp, username, dateOfBirth).Return(user, err)
|
|
},
|
|
encodeMockBehavior: func(s *mock_service.MockAuth, userID int, token string, err error) {},
|
|
repoErr: errors.New("some error"),
|
|
expectedErr: domain.InternalServerError,
|
|
},
|
|
{
|
|
name: "token_encoding_error",
|
|
hashMockBehavior: func(s *mock_service.MockAuth, p, hp string, err error) {
|
|
s.EXPECT().HashPassword(p).Return(hp, err)
|
|
},
|
|
repoMockBehavior: func(r *mock_repository.MockUser, email, hp, username string, dateOfBirth time.Time, user domain.User, err error) {
|
|
r.EXPECT().Register(email, hp, username, dateOfBirth).Return(user, err)
|
|
},
|
|
encodeMockBehavior: func(s *mock_service.MockAuth, userID int, token string, err error) {
|
|
s.EXPECT().EncodeAuthToken(userID).Return(token, err)
|
|
},
|
|
encodeErr: errors.New("some error"),
|
|
expectedErr: domain.InternalServerError,
|
|
},
|
|
}
|
|
|
|
for _, tc := range testTable {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
c := gomock.NewController(t)
|
|
defer c.Finish()
|
|
|
|
repo := mock_repository.NewMockUser(c)
|
|
auth := mock_service.NewMockAuth(c)
|
|
serv := userService{ur: repo, auth: auth}
|
|
|
|
tc.hashMockBehavior(auth, tc.ud.Password, tc.hp, tc.hashErr)
|
|
tc.repoMockBehavior(repo, tc.ud.Email, tc.hp, tc.ud.Username, tc.ud.DateOfBirth.Time, tc.repoUser, tc.repoErr)
|
|
tc.encodeMockBehavior(auth, tc.repoUser.ID, tc.expectedToken, tc.encodeErr)
|
|
|
|
token, err := serv.Register(tc.ud)
|
|
|
|
assert.Equal(t, tc.expectedToken, token)
|
|
assert.ErrorIs(t, err, tc.expectedErr)
|
|
})
|
|
}
|
|
}
|