package service import ( "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" "git.urec56.ru/urec/chat_back_go/internal/repository" 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_newMessageService(t *testing.T) { c := gomock.NewController(t) defer c.Finish() repo := mock_repository.NewMockMessage(c) l := logger.NewLogger(config.Config{Mode: "TEST"}) u := &userService{} serv := newMessageService(repo, u, l) assert.Equal(t, &messageService{repo: repo, u: u, l: l}, serv) } func TestMessageService_AddAvatarImageAndUsernameToMessage(t *testing.T) { type userServiceBehavior func(u *mock_service.MockUser, userID int, user domain.User, err error) testTable := []struct { name string userServiceBehavior userServiceBehavior inputMsg domain.RawMessage serviceInput int serviceUser domain.User serviceErr error expectedMsg domain.Message expectedErr error }{ { name: "ok", userServiceBehavior: func(u *mock_service.MockUser, userID int, user domain.User, err error) { u.EXPECT().Get(userID, true).Return(user, err) }, inputMsg: domain.RawMessage{ ID: domain.GenerateTestUUID(), Message: "some text", ImageUrl: "image", ChatID: 1, UserID: 2, CreatedAt: time.Date(2025, time.February, 2, 0, 0, 0, 0, time.UTC), AnswerID: domain.GenerateTestUUID(), AnswerMessage: "some sendMsg", AnswerImageUrl: "image2", }, serviceInput: 2, serviceUser: domain.User{ ID: 1, Role: 1, Username: "urec", Email: "mail@mail.ru", HashedPassword: "hp", AvatarImage: "avatar_image", BlackPhoenix: false, DateOfBirth: domain.CustomDate{Time: time.Date(2002, time.February, 2, 0, 0, 0, 0, time.UTC)}, DateOfRegistration: domain.CustomDate{Time: time.Date(2025, time.February, 2, 0, 0, 0, 0, time.UTC)}, }, expectedMsg: domain.Message{ ID: domain.GenerateTestUUID(), Message: "some text", ImageUrl: "image", ChatID: 1, UserID: 2, Username: "urec", AvatarImage: "avatar_image", CreatedAt: time.Date(2025, time.February, 2, 0, 0, 0, 0, time.UTC), AnswerID: domain.GenerateTestUUID(), AnswerMessage: "some sendMsg", AnswerImageUrl: "image2", }, }, { name: "any_error", userServiceBehavior: func(u *mock_service.MockUser, userID int, user domain.User, err error) { u.EXPECT().Get(userID, true).Return(user, err) }, inputMsg: domain.RawMessage{UserID: 2}, serviceInput: 2, serviceErr: domain.AnyError, expectedErr: domain.InternalServerError, }, } for _, tc := range testTable { t.Run(tc.name, func(t *testing.T) { c := gomock.NewController(t) defer c.Finish() u := mock_service.NewMockUser(c) log := logger.NewLogger(config.Config{Mode: "TEST"}) tc.userServiceBehavior(u, tc.serviceInput, tc.serviceUser, tc.serviceErr) serv := &messageService{u: u, l: log} res, err := serv.AddAvatarImageAndUsernameToMessage(tc.inputMsg) assert.Equal(t, tc.expectedMsg, res) assert.ErrorIs(t, err, tc.expectedErr) }) } } func TestMessageService_AddAvatarImageAndUsernameToMessages(t *testing.T) { type userServiceBehavior func(u *mock_service.MockUser, userID int, user domain.User, err error) testTable := []struct { name string userServiceBehavior userServiceBehavior inputMsgs []domain.RawMessage serviceInput int serviceUser domain.User serviceErr error expectedMsgs []domain.Message }{ { name: "ok", userServiceBehavior: func(u *mock_service.MockUser, userID int, user domain.User, err error) { u.EXPECT().Get(userID, true).Return(user, err) }, inputMsgs: []domain.RawMessage{ { ID: domain.GenerateTestUUID(), Message: "some text", ImageUrl: "image", ChatID: 1, UserID: 2, CreatedAt: time.Date(2025, time.February, 2, 0, 0, 0, 0, time.UTC), AnswerID: domain.GenerateTestUUID(), AnswerMessage: "some sendMsg", AnswerImageUrl: "image2", }, }, serviceInput: 2, serviceUser: domain.User{ ID: 1, Role: 1, Username: "urec", Email: "mail@mail.ru", HashedPassword: "hp", AvatarImage: "avatar_image", BlackPhoenix: false, DateOfBirth: domain.CustomDate{Time: time.Date(2002, time.February, 2, 0, 0, 0, 0, time.UTC)}, DateOfRegistration: domain.CustomDate{Time: time.Date(2025, time.February, 2, 0, 0, 0, 0, time.UTC)}, }, expectedMsgs: []domain.Message{ { ID: domain.GenerateTestUUID(), Message: "some text", ImageUrl: "image", ChatID: 1, UserID: 2, Username: "urec", AvatarImage: "avatar_image", CreatedAt: time.Date(2025, time.February, 2, 0, 0, 0, 0, time.UTC), AnswerID: domain.GenerateTestUUID(), AnswerMessage: "some sendMsg", AnswerImageUrl: "image2", }, }, }, { name: "any_error", userServiceBehavior: func(u *mock_service.MockUser, userID int, user domain.User, err error) { u.EXPECT().Get(userID, true).Return(user, err) }, inputMsgs: []domain.RawMessage{{UserID: 2}}, serviceInput: 2, serviceErr: domain.AnyError, expectedMsgs: []domain.Message{}, }, } for _, tc := range testTable { t.Run(tc.name, func(t *testing.T) { c := gomock.NewController(t) defer c.Finish() u := mock_service.NewMockUser(c) log := logger.NewLogger(config.Config{Mode: "TEST"}) tc.userServiceBehavior(u, tc.serviceInput, tc.serviceUser, tc.serviceErr) serv := &messageService{u: u, l: log} msgs := serv.AddAvatarImageAndUsernameToMessages(tc.inputMsgs) assert.Equal(t, tc.expectedMsgs, msgs) }) } } func TestMessageService_GetRaw(t *testing.T) { type repoBehavior func(r *mock_repository.MockMessage, input domain.UUID, msg domain.RawMessage, err error) testTable := []struct { name string repoBehavior repoBehavior inputID domain.UUID repoInput domain.UUID repoMsg domain.RawMessage repoErr error expectedMessage domain.RawMessage expectedErr error }{ { name: "ok", repoBehavior: func(r *mock_repository.MockMessage, input domain.UUID, msg domain.RawMessage, err error) { r.EXPECT().Get(input).Return(msg, err) }, inputID: domain.GenerateTestUUID(), repoInput: domain.GenerateTestUUID(), repoMsg: domain.RawMessage{ ID: domain.GenerateTestUUID(), Message: "sendMsg", ImageUrl: "image", ChatID: 1, UserID: 2, CreatedAt: time.Date(2025, time.February, 2, 0, 0, 0, 0, time.UTC), AnswerID: domain.GenerateTestUUID(), AnswerMessage: "msg1", AnswerImageUrl: "image2", }, expectedMessage: domain.RawMessage{ ID: domain.GenerateTestUUID(), Message: "sendMsg", ImageUrl: "image", ChatID: 1, UserID: 2, CreatedAt: time.Date(2025, time.February, 2, 0, 0, 0, 0, time.UTC), AnswerID: domain.GenerateTestUUID(), AnswerMessage: "msg1", AnswerImageUrl: "image2", }, }, { name: "any_error", repoBehavior: func(r *mock_repository.MockMessage, input domain.UUID, msg domain.RawMessage, err error) { r.EXPECT().Get(input).Return(msg, err) }, inputID: domain.GenerateTestUUID(), repoInput: domain.GenerateTestUUID(), repoErr: domain.AnyError, 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.NewMockMessage(c) log := logger.NewLogger(config.Config{Mode: "TEST"}) tc.repoBehavior(repo, tc.repoInput, tc.repoMsg, tc.repoErr) serv := &messageService{repo: repo, l: log} msg, err := serv.GetRaw(tc.inputID) assert.Equal(t, msg, tc.expectedMessage) assert.ErrorIs(t, err, tc.expectedErr) }) } } func TestMessageService_GetMessage(t *testing.T) { type repoBehavior func(r *mock_repository.MockMessage, input domain.UUID, msg domain.RawMessage, err error) type serviceBehavior func(s *mock_service.MockUser, userID int, user domain.User, err error) testTable := []struct { name string repoBehavior repoBehavior serviceBehavior serviceBehavior inputID domain.UUID repoInput domain.UUID repoMsg domain.RawMessage serviceInput int serviceUser domain.User serviceErr error repoErr error expectedMessage domain.Message expectedErr error }{ { name: "ok", repoBehavior: func(r *mock_repository.MockMessage, input domain.UUID, msg domain.RawMessage, err error) { r.EXPECT().Get(input).Return(msg, err) }, serviceBehavior: func(s *mock_service.MockUser, userID int, user domain.User, err error) { s.EXPECT().Get(userID, true).Return(user, err) }, inputID: domain.GenerateTestUUID(), repoInput: domain.GenerateTestUUID(), repoMsg: domain.RawMessage{ ID: domain.GenerateTestUUID(), Message: "sendMsg", ImageUrl: "image", ChatID: 1, UserID: 2, CreatedAt: time.Date(2025, time.February, 2, 0, 0, 0, 0, time.UTC), AnswerID: domain.GenerateTestUUID(), AnswerMessage: "msg1", AnswerImageUrl: "image2", }, serviceInput: 2, serviceUser: domain.User{ ID: 2, Role: 1, Username: "username", Email: "mail@mail.ru", HashedPassword: "hp", AvatarImage: "image", BlackPhoenix: true, DateOfBirth: domain.CustomDate{Time: time.Date(2002, time.February, 2, 0, 0, 0, 0, time.UTC)}, DateOfRegistration: domain.CustomDate{Time: time.Date(2025, time.February, 2, 0, 0, 0, 0, time.UTC)}, }, expectedMessage: domain.Message{ ID: domain.GenerateTestUUID(), Message: "sendMsg", ImageUrl: "image", ChatID: 1, UserID: 2, Username: "username", AvatarImage: "image", CreatedAt: time.Date(2025, time.February, 2, 0, 0, 0, 0, time.UTC), AnswerID: domain.GenerateTestUUID(), AnswerMessage: "msg1", AnswerImageUrl: "image2", }, }, { name: "repoErr", repoBehavior: func(r *mock_repository.MockMessage, input domain.UUID, msg domain.RawMessage, err error) { r.EXPECT().Get(input).Return(msg, err) }, serviceBehavior: func(s *mock_service.MockUser, userID int, user domain.User, err error) {}, inputID: domain.GenerateTestUUID(), repoInput: domain.GenerateTestUUID(), repoErr: domain.AnyError, expectedErr: domain.InternalServerError, }, { name: "ok", repoBehavior: func(r *mock_repository.MockMessage, input domain.UUID, msg domain.RawMessage, err error) { r.EXPECT().Get(input).Return(msg, err) }, serviceBehavior: func(s *mock_service.MockUser, userID int, user domain.User, err error) { s.EXPECT().Get(userID, true).Return(user, err) }, inputID: domain.GenerateTestUUID(), repoInput: domain.GenerateTestUUID(), repoMsg: domain.RawMessage{ ID: domain.GenerateTestUUID(), Message: "sendMsg", ImageUrl: "image", ChatID: 1, UserID: 2, CreatedAt: time.Date(2025, time.February, 2, 0, 0, 0, 0, time.UTC), AnswerID: domain.GenerateTestUUID(), AnswerMessage: "msg1", AnswerImageUrl: "image2", }, serviceInput: 2, serviceErr: domain.AnyError, 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.NewMockMessage(c) u := mock_service.NewMockUser(c) log := logger.NewLogger(config.Config{Mode: "TEST"}) tc.repoBehavior(repo, tc.repoInput, tc.repoMsg, tc.repoErr) tc.serviceBehavior(u, tc.serviceInput, tc.serviceUser, tc.serviceErr) serv := &messageService{repo: repo, u: u, l: log} msg, err := serv.GetMessage(tc.inputID) assert.Equal(t, msg, tc.expectedMessage) assert.ErrorIs(t, err, tc.expectedErr) }) } } func TestMessageService_GetPinned(t *testing.T) { type repoGetPinnedIDsBehavior func(r *mock_repository.MockMessage, chatID int, IDs []domain.UUID, err error) type repoGetByIDsBehavior func(r *mock_repository.MockMessage, IDs []domain.UUID, msgs []domain.RawMessage, err error) type userServiceBehavior func(s *mock_service.MockUser, userID int, user domain.User, err error) type repo1Data struct { chatID int IDs []domain.UUID err error } type repo2Data struct { IDs []domain.UUID msgs []domain.RawMessage err error } type serviceData struct { userID int user domain.User err error } testTable := []struct { name string repoGetPinnedIDsBehavior repoGetPinnedIDsBehavior repoGetByIDsBehavior repoGetByIDsBehavior userServiceBehavior userServiceBehavior repo1Data repo1Data repo2Data repo2Data serviceData serviceData chatID int expectedMsgs []domain.Message expectedErr error }{ { name: "ok", repoGetPinnedIDsBehavior: func(r *mock_repository.MockMessage, chatID int, IDs []domain.UUID, err error) { r.EXPECT().GetPinnedIDs(chatID).Return(IDs, err) }, repoGetByIDsBehavior: func(r *mock_repository.MockMessage, IDs []domain.UUID, msgs []domain.RawMessage, err error) { r.EXPECT().GetByIDs(IDs).Return(msgs, err) }, userServiceBehavior: func(s *mock_service.MockUser, userID int, user domain.User, err error) { s.EXPECT().Get(userID, true).Return(user, err) }, repo1Data: repo1Data{ chatID: 32, IDs: []domain.UUID{domain.GenerateTestUUID()}, }, repo2Data: repo2Data{ IDs: []domain.UUID{domain.GenerateTestUUID()}, msgs: []domain.RawMessage{ { ID: domain.GenerateTestUUID(), Message: "message", ImageUrl: "image", ChatID: 32, UserID: 2, CreatedAt: time.Date(2025, time.February, 2, 0, 0, 0, 0, time.UTC), AnswerID: domain.GenerateTestUUID(), AnswerMessage: "msg2", AnswerImageUrl: "image2", }, }, }, serviceData: serviceData{ userID: 2, user: domain.User{ ID: 2, Role: 1, Username: "username", Email: "mail@mail.ru", HashedPassword: "hp", AvatarImage: "avatar_image", BlackPhoenix: true, DateOfBirth: domain.CustomDate{Time: time.Date(2002, time.February, 2, 0, 0, 0, 0, time.UTC)}, DateOfRegistration: domain.CustomDate{Time: time.Date(2025, time.February, 2, 0, 0, 0, 0, time.UTC)}, }, }, chatID: 32, expectedMsgs: []domain.Message{ { ID: domain.GenerateTestUUID(), Message: "message", ImageUrl: "image", ChatID: 32, UserID: 2, Username: "username", AvatarImage: "avatar_image", CreatedAt: time.Date(2025, time.February, 2, 0, 0, 0, 0, time.UTC), AnswerID: domain.GenerateTestUUID(), AnswerMessage: "msg2", AnswerImageUrl: "image2", }, }, }, { name: "GetPinnedIDs_error", repoGetPinnedIDsBehavior: func(r *mock_repository.MockMessage, chatID int, IDs []domain.UUID, err error) { r.EXPECT().GetPinnedIDs(chatID).Return(IDs, err) }, repoGetByIDsBehavior: func(r *mock_repository.MockMessage, IDs []domain.UUID, msgs []domain.RawMessage, err error) {}, userServiceBehavior: func(s *mock_service.MockUser, userID int, user domain.User, err error) {}, repo1Data: repo1Data{ chatID: 32, err: domain.AnyError, }, chatID: 32, expectedErr: domain.InternalServerError, }, { name: "GetByIDs_error", repoGetPinnedIDsBehavior: func(r *mock_repository.MockMessage, chatID int, IDs []domain.UUID, err error) { r.EXPECT().GetPinnedIDs(chatID).Return(IDs, err) }, repoGetByIDsBehavior: func(r *mock_repository.MockMessage, IDs []domain.UUID, msgs []domain.RawMessage, err error) { r.EXPECT().GetByIDs(IDs).Return(msgs, err) }, userServiceBehavior: func(s *mock_service.MockUser, userID int, user domain.User, err error) {}, repo1Data: repo1Data{ chatID: 32, IDs: []domain.UUID{domain.GenerateTestUUID()}, }, repo2Data: repo2Data{ IDs: []domain.UUID{domain.GenerateTestUUID()}, err: domain.AnyError, }, chatID: 32, 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.NewMockMessage(c) userServ := mock_service.NewMockUser(c) log := logger.NewLogger(config.Config{Mode: "TEST"}) tc.repoGetPinnedIDsBehavior(repo, tc.repo1Data.chatID, tc.repo1Data.IDs, tc.repo1Data.err) tc.repoGetByIDsBehavior(repo, tc.repo2Data.IDs, tc.repo2Data.msgs, tc.repo2Data.err) tc.userServiceBehavior(userServ, tc.serviceData.userID, tc.serviceData.user, tc.serviceData.err) serv := &messageService{repo: repo, u: userServ, l: log} msgs, err := serv.GetPinned(tc.chatID) assert.Equal(t, tc.expectedMsgs, msgs) assert.ErrorIs(t, err, tc.expectedErr) }) } } func TestMessageService_GetSome(t *testing.T) { type repoBehavior func(r *mock_repository.MockMessage, messagesInfo repository.GetSome, msgs []domain.RawMessage, err error) type serviceBehavior func(s *mock_service.MockUser, userID int, user domain.User, err error) type repoData struct { messagesInfo repository.GetSome msgs []domain.RawMessage err error } type serviceData struct { userID int user domain.User err error } testTable := []struct { name string repoBehavior repoBehavior serviceBehavior serviceBehavior repoData repoData serviceData serviceData chatID, offset, limit int expectedMsgs []domain.Message expectedErr error }{ { name: "ok", repoBehavior: func(r *mock_repository.MockMessage, messagesInfo repository.GetSome, msgs []domain.RawMessage, err error) { r.EXPECT().GetSome(messagesInfo).Return(msgs, err) }, serviceBehavior: func(s *mock_service.MockUser, userID int, user domain.User, err error) { s.EXPECT().Get(userID, true).Return(user, err) }, repoData: repoData{ messagesInfo: repository.GetSome{ChatID: 15, Offset: 10, Limit: 15}, msgs: []domain.RawMessage{ { ID: domain.GenerateTestUUID(), Message: "message", ImageUrl: "image", ChatID: 15, UserID: 2, CreatedAt: time.Date(2025, time.February, 2, 0, 0, 0, 0, time.UTC), AnswerID: domain.GenerateTestUUID(), AnswerMessage: "msg2", AnswerImageUrl: "image2", }, }, }, serviceData: serviceData{ userID: 2, user: domain.User{ ID: 2, Role: 1, Username: "username", Email: "mail@mail.ru", HashedPassword: "hp", AvatarImage: "avatar_image", BlackPhoenix: true, DateOfBirth: domain.CustomDate{Time: time.Date(2002, time.February, 2, 0, 0, 0, 0, time.UTC)}, DateOfRegistration: domain.CustomDate{Time: time.Date(2025, time.February, 2, 0, 0, 0, 0, time.UTC)}, }, }, chatID: 15, offset: 10, limit: 15, expectedMsgs: []domain.Message{ { ID: domain.GenerateTestUUID(), Message: "message", ImageUrl: "image", ChatID: 15, UserID: 2, Username: "username", AvatarImage: "avatar_image", CreatedAt: time.Date(2025, time.February, 2, 0, 0, 0, 0, time.UTC), AnswerID: domain.GenerateTestUUID(), AnswerMessage: "msg2", AnswerImageUrl: "image2", }, }, }, { name: "repo_error", repoBehavior: func(r *mock_repository.MockMessage, messagesInfo repository.GetSome, msgs []domain.RawMessage, err error) { r.EXPECT().GetSome(messagesInfo).Return(msgs, err) }, serviceBehavior: func(s *mock_service.MockUser, userID int, user domain.User, err error) {}, repoData: repoData{ messagesInfo: repository.GetSome{ChatID: 15, Offset: 10, Limit: 15}, err: domain.AnyError, }, chatID: 15, offset: 10, limit: 15, 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.NewMockMessage(c) userServ := mock_service.NewMockUser(c) log := logger.NewLogger(config.Config{Mode: "TEST"}) tc.repoBehavior(repo, tc.repoData.messagesInfo, tc.repoData.msgs, tc.repoData.err) tc.serviceBehavior(userServ, tc.serviceData.userID, tc.serviceData.user, tc.serviceData.err) serv := &messageService{repo: repo, u: userServ, l: log} msgs, err := serv.GetSome(tc.chatID, tc.offset, tc.limit) assert.Equal(t, tc.expectedMsgs, msgs) assert.ErrorIs(t, tc.expectedErr, err) }) } } func TestMessageService_SendMessage(t *testing.T) { type getRawBehavior func(r *mock_repository.MockMessage, answerID domain.UUID, msg domain.RawMessage, err error) type sendBehavior func(r *mock_repository.MockMessage, msg repository.SendMessage, rawMsg domain.RawMessage, err error) type userGetBehavior func(s *mock_service.MockUser, userID int, user domain.User, err error) type getRawData struct { answerID domain.UUID msg domain.RawMessage err error } type sendData struct { sendMsg repository.SendMessage rawMsg domain.RawMessage err error } type userGetData struct { userID int user domain.User err error } type input struct { userID, chatID int message domain.SendMessage } testTable := []struct { name string getRawBehavior getRawBehavior sendBehavior sendBehavior userGetBehavior userGetBehavior getRawData getRawData sendData sendData userGetData userGetData input input expectedMsg domain.Message expectedErr error }{ { name: "message_without_answer", getRawBehavior: func(r *mock_repository.MockMessage, answerID domain.UUID, msg domain.RawMessage, err error) {}, sendBehavior: func(r *mock_repository.MockMessage, msg repository.SendMessage, rawMsg domain.RawMessage, err error) { r.EXPECT().Send(msg).Return(rawMsg, err) }, userGetBehavior: func(s *mock_service.MockUser, userID int, user domain.User, err error) { s.EXPECT().Get(userID, true).Return(user, err) }, input: input{ userID: 1, chatID: 2, message: domain.SendMessage{ Flag: "send", Message: "msg", ImageUrl: "image", }, }, sendData: sendData{ sendMsg: repository.SendMessage{ Message: "msg", ImageUrl: "image", ChatID: 2, UserID: 1, }, rawMsg: domain.RawMessage{ ID: domain.GenerateTestUUID(), Message: "msg", ImageUrl: "image", ChatID: 2, UserID: 1, CreatedAt: time.Date(2025, time.February, 2, 0, 0, 0, 0, time.UTC), }, }, userGetData: userGetData{ userID: 1, user: domain.User{ ID: 1, Role: 1, Username: "name", Email: "mail@mail.ru", HashedPassword: "hp", AvatarImage: "avatar_image", BlackPhoenix: true, DateOfBirth: domain.CustomDate{Time: time.Date(2002, time.February, 2, 0, 0, 0, 0, time.UTC)}, DateOfRegistration: domain.CustomDate{Time: time.Date(2025, time.February, 2, 0, 0, 0, 0, time.UTC)}, }, }, expectedMsg: domain.Message{ ID: domain.GenerateTestUUID(), Message: "msg", ImageUrl: "image", ChatID: 2, UserID: 1, Username: "name", AvatarImage: "avatar_image", CreatedAt: time.Date(2025, time.February, 2, 0, 0, 0, 0, time.UTC), }, }, { name: "message_with_answer", getRawBehavior: func(r *mock_repository.MockMessage, answerID domain.UUID, msg domain.RawMessage, err error) { r.EXPECT().Get(answerID).Return(msg, err) }, sendBehavior: func(r *mock_repository.MockMessage, msg repository.SendMessage, rawMsg domain.RawMessage, err error) { r.EXPECT().Send(msg).Return(rawMsg, err) }, userGetBehavior: func(s *mock_service.MockUser, userID int, user domain.User, err error) { s.EXPECT().Get(userID, true).Return(user, err) }, input: input{ userID: 1, chatID: 2, message: domain.SendMessage{ Flag: "send", Message: "msg", ImageUrl: "image", Answer: domain.GenerateTestUUID(), }, }, getRawData: getRawData{ answerID: domain.GenerateTestUUID(), msg: domain.RawMessage{ ID: domain.GenerateTestUUID(), Message: "answer_msg", ImageUrl: "answer_image", ChatID: 2, UserID: 3, CreatedAt: time.Date(2025, time.February, 1, 0, 0, 0, 0, time.UTC), }, }, sendData: sendData{ sendMsg: repository.SendMessage{ Message: "msg", ImageUrl: "image", ChatID: 2, UserID: 1, AnswerID: domain.GenerateTestUUID(), AnswerMessage: "answer_msg", AnswerImageUrl: "answer_image", }, rawMsg: domain.RawMessage{ ID: domain.GenerateTestUUID(), Message: "msg", ImageUrl: "image", ChatID: 2, UserID: 1, CreatedAt: time.Date(2025, time.February, 2, 0, 0, 0, 0, time.UTC), AnswerID: domain.GenerateTestUUID(), AnswerMessage: "answer_msg", AnswerImageUrl: "answer_image", }, }, userGetData: userGetData{ userID: 1, user: domain.User{ ID: 1, Role: 1, Username: "name", Email: "mail@mail.ru", HashedPassword: "hp", AvatarImage: "avatar_image", BlackPhoenix: true, DateOfBirth: domain.CustomDate{Time: time.Date(2002, time.February, 2, 0, 0, 0, 0, time.UTC)}, DateOfRegistration: domain.CustomDate{Time: time.Date(2025, time.February, 2, 0, 0, 0, 0, time.UTC)}, }, }, expectedMsg: domain.Message{ ID: domain.GenerateTestUUID(), Message: "msg", ImageUrl: "image", ChatID: 2, UserID: 1, Username: "name", AvatarImage: "avatar_image", CreatedAt: time.Date(2025, time.February, 2, 0, 0, 0, 0, time.UTC), AnswerID: domain.GenerateTestUUID(), AnswerMessage: "answer_msg", AnswerImageUrl: "answer_image", }, }, { name: "message_without_answer_send_error", getRawBehavior: func(r *mock_repository.MockMessage, answerID domain.UUID, msg domain.RawMessage, err error) {}, sendBehavior: func(r *mock_repository.MockMessage, msg repository.SendMessage, rawMsg domain.RawMessage, err error) { r.EXPECT().Send(msg).Return(rawMsg, err) }, userGetBehavior: func(s *mock_service.MockUser, userID int, user domain.User, err error) {}, input: input{ userID: 1, chatID: 2, message: domain.SendMessage{ Flag: "send", Message: "msg", ImageUrl: "image", }, }, sendData: sendData{ sendMsg: repository.SendMessage{ Message: "msg", ImageUrl: "image", ChatID: 2, UserID: 1, }, err: domain.AnyError, }, expectedErr: domain.InternalServerError, }, { name: "message_with_answer_getRaw_error", getRawBehavior: func(r *mock_repository.MockMessage, answerID domain.UUID, msg domain.RawMessage, err error) { r.EXPECT().Get(answerID).Return(msg, err) }, sendBehavior: func(r *mock_repository.MockMessage, msg repository.SendMessage, rawMsg domain.RawMessage, err error) { }, userGetBehavior: func(s *mock_service.MockUser, userID int, user domain.User, err error) {}, input: input{ userID: 1, chatID: 2, message: domain.SendMessage{ Flag: "send", Message: "msg", ImageUrl: "image", Answer: domain.GenerateTestUUID(), }, }, getRawData: getRawData{ answerID: domain.GenerateTestUUID(), err: domain.AnyError, }, expectedErr: domain.InternalServerError, }, { name: "message_with_answer_send_error", getRawBehavior: func(r *mock_repository.MockMessage, answerID domain.UUID, msg domain.RawMessage, err error) { r.EXPECT().Get(answerID).Return(msg, err) }, sendBehavior: func(r *mock_repository.MockMessage, msg repository.SendMessage, rawMsg domain.RawMessage, err error) { r.EXPECT().Send(msg).Return(rawMsg, err) }, userGetBehavior: func(s *mock_service.MockUser, userID int, user domain.User, err error) {}, input: input{ userID: 1, chatID: 2, message: domain.SendMessage{ Flag: "send", Message: "msg", ImageUrl: "image", Answer: domain.GenerateTestUUID(), }, }, getRawData: getRawData{ answerID: domain.GenerateTestUUID(), msg: domain.RawMessage{ ID: domain.GenerateTestUUID(), Message: "answer_msg", ImageUrl: "answer_image", ChatID: 2, UserID: 3, CreatedAt: time.Date(2025, time.February, 1, 0, 0, 0, 0, time.UTC), }, }, sendData: sendData{ sendMsg: repository.SendMessage{ Message: "msg", ImageUrl: "image", ChatID: 2, UserID: 1, AnswerID: domain.GenerateTestUUID(), AnswerMessage: "answer_msg", AnswerImageUrl: "answer_image", }, err: domain.AnyError, }, expectedErr: domain.InternalServerError, }, { name: "get_user_error", getRawBehavior: func(r *mock_repository.MockMessage, answerID domain.UUID, msg domain.RawMessage, err error) {}, sendBehavior: func(r *mock_repository.MockMessage, msg repository.SendMessage, rawMsg domain.RawMessage, err error) { r.EXPECT().Send(msg).Return(rawMsg, err) }, userGetBehavior: func(s *mock_service.MockUser, userID int, user domain.User, err error) { s.EXPECT().Get(userID, true).Return(user, err) }, input: input{ userID: 1, chatID: 2, message: domain.SendMessage{ Flag: "send", Message: "msg", ImageUrl: "image", }, }, sendData: sendData{ sendMsg: repository.SendMessage{ Message: "msg", ImageUrl: "image", ChatID: 2, UserID: 1, }, rawMsg: domain.RawMessage{ ID: domain.GenerateTestUUID(), Message: "msg", ImageUrl: "image", ChatID: 2, UserID: 1, CreatedAt: time.Date(2025, time.February, 2, 0, 0, 0, 0, time.UTC), }, }, userGetData: userGetData{ userID: 1, err: domain.AnyError, }, 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.NewMockMessage(c) log := logger.NewLogger(config.Config{Mode: "TEST"}) userServ := mock_service.NewMockUser(c) tc.getRawBehavior(repo, tc.getRawData.answerID, tc.getRawData.msg, tc.getRawData.err) tc.sendBehavior(repo, tc.sendData.sendMsg, tc.sendData.rawMsg, tc.sendData.err) tc.userGetBehavior(userServ, tc.userGetData.userID, tc.userGetData.user, tc.userGetData.err) serv := &messageService{repo: repo, u: userServ, l: log} msg, err := serv.SendMessage(tc.input.userID, tc.input.chatID, tc.input.message) assert.Equal(t, tc.expectedMsg, msg) assert.ErrorIs(t, err, tc.expectedErr) }) } } func TestMessageService_Delete(t *testing.T) { type repoBehavior func(r *mock_repository.MockMessage, ID domain.UUID, err error) testTable := []struct { name string repoBehavior repoBehavior ID domain.UUID repoID domain.UUID repoErr error expectedErr error }{ { name: "ok", repoBehavior: func(r *mock_repository.MockMessage, ID domain.UUID, err error) { r.EXPECT().Delete(ID).Return(err) }, ID: domain.GenerateTestUUID(), repoID: domain.GenerateTestUUID(), }, { name: "any_error", repoBehavior: func(r *mock_repository.MockMessage, ID domain.UUID, err error) { r.EXPECT().Delete(ID).Return(err) }, ID: domain.GenerateTestUUID(), repoID: domain.GenerateTestUUID(), repoErr: domain.AnyError, 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.NewMockMessage(c) log := logger.NewLogger(config.Config{Mode: "TEST"}) tc.repoBehavior(repo, tc.repoID, tc.repoErr) serv := &messageService{repo: repo, l: log} err := serv.Delete(tc.ID) assert.ErrorIs(t, err, tc.expectedErr) }) } } func TestMessageService_Edit(t *testing.T) { type repoBehavior func(r *mock_repository.MockMessage, msg repository.EditMessage, err error) testTable := []struct { name string repoBehavior repoBehavior ID domain.UUID newMessage, newImageUrl string newMsg repository.EditMessage repoErr error expectedErr error }{ { name: "ok", repoBehavior: func(r *mock_repository.MockMessage, msg repository.EditMessage, err error) { r.EXPECT().Edit(msg).Return(err) }, ID: domain.GenerateTestUUID(), newMessage: "new_message", newImageUrl: "new_image_url", newMsg: repository.EditMessage{ ID: domain.GenerateTestUUID(), Message: "new_message", ImageUrl: "new_image_url", }, }, { name: "any_error", repoBehavior: func(r *mock_repository.MockMessage, msg repository.EditMessage, err error) { r.EXPECT().Edit(msg).Return(err) }, ID: domain.GenerateTestUUID(), newMessage: "new_message", newImageUrl: "new_image_url", newMsg: repository.EditMessage{ ID: domain.GenerateTestUUID(), Message: "new_message", ImageUrl: "new_image_url", }, repoErr: domain.AnyError, 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.NewMockMessage(c) log := logger.NewLogger(config.Config{Mode: "TEST"}) tc.repoBehavior(repo, tc.newMsg, tc.repoErr) serv := &messageService{repo: repo, l: log} err := serv.Edit(tc.ID, tc.newMessage, tc.newImageUrl) assert.ErrorIs(t, err, tc.expectedErr) }) } } func TestMessageService_Pin(t *testing.T) { type repo1Behavior func(r *mock_repository.MockMessage, msg repository.PinMessage, err error) type repo2Behavior func(r *mock_repository.MockMessage, ID domain.UUID, msg domain.RawMessage, err error) type serviceBehavior func(s *mock_service.MockUser, userID int, user domain.User, err error) type repo2Data struct { ID domain.UUID msg domain.RawMessage err error } type serviceData struct { userID int user domain.User err error } testTable := []struct { name string repo1Behavior repo1Behavior repo2Behavior repo2Behavior serviceBehavior serviceBehavior repo2Data repo2Data serviceData serviceData pinMsg repository.PinMessage chatID, userID int messageID domain.UUID repoErr error expectedMsg domain.Message expectedErr error }{ { name: "ok", repo1Behavior: func(r *mock_repository.MockMessage, msg repository.PinMessage, err error) { r.EXPECT().Pin(msg).Return(err) }, repo2Behavior: func(r *mock_repository.MockMessage, ID domain.UUID, msg domain.RawMessage, err error) { r.EXPECT().Get(ID).Return(msg, err) }, serviceBehavior: func(s *mock_service.MockUser, userID int, user domain.User, err error) { s.EXPECT().Get(userID, true).Return(user, err) }, repo2Data: repo2Data{ ID: domain.GenerateTestUUID(), msg: domain.RawMessage{ ID: domain.GenerateTestUUID(), Message: "sendMsg", ImageUrl: "image", ChatID: 17, UserID: 3, CreatedAt: time.Date(2025, time.February, 2, 0, 0, 0, 0, time.UTC), AnswerID: domain.GenerateTestUUID(), AnswerMessage: "answer_msg", AnswerImageUrl: "answer_image", }, }, serviceData: serviceData{ userID: 3, user: domain.User{ ID: 3, Role: 1, Username: "name", Email: "mail@mail.ru", HashedPassword: "hp", AvatarImage: "avatar_image", BlackPhoenix: true, DateOfBirth: domain.CustomDate{Time: time.Date(2002, time.February, 2, 0, 0, 0, 0, time.UTC)}, DateOfRegistration: domain.CustomDate{Time: time.Date(2025, time.February, 2, 0, 0, 0, 0, time.UTC)}, }, }, pinMsg: repository.PinMessage{MessageID: domain.GenerateTestUUID(), ChatID: 17, UserID: 2}, chatID: 17, userID: 2, messageID: domain.GenerateTestUUID(), expectedMsg: domain.Message{ ID: domain.GenerateTestUUID(), Message: "sendMsg", ImageUrl: "image", ChatID: 17, UserID: 3, Username: "name", AvatarImage: "avatar_image", CreatedAt: time.Date(2025, time.February, 2, 0, 0, 0, 0, time.UTC), AnswerID: domain.GenerateTestUUID(), AnswerMessage: "answer_msg", AnswerImageUrl: "answer_image", }, }, { name: "message_already_pinned", repo1Behavior: func(r *mock_repository.MockMessage, msg repository.PinMessage, err error) { r.EXPECT().Pin(msg).Return(err) }, repo2Behavior: func(r *mock_repository.MockMessage, ID domain.UUID, msg domain.RawMessage, err error) {}, serviceBehavior: func(s *mock_service.MockUser, userID int, user domain.User, err error) {}, pinMsg: repository.PinMessage{MessageID: domain.GenerateTestUUID(), ChatID: 17, UserID: 2}, chatID: 17, userID: 2, messageID: domain.GenerateTestUUID(), repoErr: domain.MessageAlreadyPinnedError, expectedErr: domain.MessageAlreadyPinnedError, }, { name: "repo_error", repo1Behavior: func(r *mock_repository.MockMessage, msg repository.PinMessage, err error) { r.EXPECT().Pin(msg).Return(err) }, repo2Behavior: func(r *mock_repository.MockMessage, ID domain.UUID, msg domain.RawMessage, err error) {}, serviceBehavior: func(s *mock_service.MockUser, userID int, user domain.User, err error) {}, pinMsg: repository.PinMessage{MessageID: domain.GenerateTestUUID(), ChatID: 17, UserID: 2}, chatID: 17, userID: 2, messageID: domain.GenerateTestUUID(), repoErr: domain.AnyError, expectedErr: domain.InternalServerError, }, { name: "GetMessage_error", repo1Behavior: func(r *mock_repository.MockMessage, msg repository.PinMessage, err error) { r.EXPECT().Pin(msg).Return(err) }, repo2Behavior: func(r *mock_repository.MockMessage, ID domain.UUID, msg domain.RawMessage, err error) { r.EXPECT().Get(ID).Return(msg, err) }, serviceBehavior: func(s *mock_service.MockUser, userID int, user domain.User, err error) {}, repo2Data: repo2Data{ ID: domain.GenerateTestUUID(), err: domain.AnyError, }, pinMsg: repository.PinMessage{MessageID: domain.GenerateTestUUID(), ChatID: 17, UserID: 2}, chatID: 17, userID: 2, messageID: domain.GenerateTestUUID(), 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.NewMockMessage(c) userServ := mock_service.NewMockUser(c) log := logger.NewLogger(config.Config{Mode: "TEST"}) tc.repo1Behavior(repo, tc.pinMsg, tc.repoErr) tc.repo2Behavior(repo, tc.repo2Data.ID, tc.repo2Data.msg, tc.repo2Data.err) tc.serviceBehavior(userServ, tc.serviceData.userID, tc.serviceData.user, tc.serviceData.err) serv := &messageService{repo: repo, u: userServ, l: log} msg, err := serv.Pin(tc.chatID, tc.userID, tc.messageID) assert.Equal(t, tc.expectedMsg, msg) assert.ErrorIs(t, err, tc.expectedErr) }) } } func TestMessageService_Unpin(t *testing.T) { type repoBehavior func(r *mock_repository.MockMessage, msg repository.UnpinMessage, err error) testTable := []struct { name string repoBehavior repoBehavior repoMsg repository.UnpinMessage chatID int messageID domain.UUID repoErr error expectedErr error }{ { name: "ok", repoBehavior: func(r *mock_repository.MockMessage, msg repository.UnpinMessage, err error) { r.EXPECT().Unpin(msg).Return(err) }, repoMsg: repository.UnpinMessage{MessageID: domain.GenerateTestUUID(), ChatID: 2}, chatID: 2, messageID: domain.GenerateTestUUID(), }, { name: "repo_error", repoBehavior: func(r *mock_repository.MockMessage, msg repository.UnpinMessage, err error) { r.EXPECT().Unpin(msg).Return(err) }, repoMsg: repository.UnpinMessage{MessageID: domain.GenerateTestUUID(), ChatID: 2}, chatID: 2, messageID: domain.GenerateTestUUID(), repoErr: domain.AnyError, 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.NewMockMessage(c) log := logger.NewLogger(config.Config{Mode: "TEST"}) tc.repoBehavior(repo, tc.repoMsg, tc.repoErr) serv := &messageService{repo: repo, l: log} err := serv.Unpin(tc.chatID, tc.messageID) assert.ErrorIs(t, err, tc.expectedErr) }) } }