using Govor.Application.Exceptions.VerifyFriendship; using Govor.Application.Interfaces; using Govor.Application.Interfaces.Medias; using Govor.Application.Interfaces.Messages.Parameters; using Govor.Application.PrivateUserChats; using Govor.Application.Services.Messages; using Govor.Domain.Models; using Govor.Domain.Models.Messages; using Govor.Domain.Repositories.Groups; using Govor.Domain.Repositories.Messages; using Govor.Domain.Repositories.PrivateChats; using Govor.Domain.Repositories.Users; using Govor.Data.Repositories.Exceptions; using Microsoft.Extensions.Logging; using Moq; namespace Govor.Application.Tests.Services.Messages; [TestFixture] public class MessageCommandServiceTests { private Mock _mockMessagesRepo; private Mock _mockUsersRepo; private Mock _mockGroupsRepo; private Mock _mockPrivateChatsRepo; private Mock _mockVerifyFriendship; private Mock _mockMediaService; private Mock _mockUserPrivateChatCreator; private Mock> _mockLogger; private MessageCommandService _messageService; [SetUp] public void SetUp() { _mockMessagesRepo = new Mock(); _mockUsersRepo = new Mock(); _mockGroupsRepo = new Mock(); _mockPrivateChatsRepo = new Mock(); _mockVerifyFriendship = new Mock(); _mockMediaService = new Mock(); _mockUserPrivateChatCreator = new Mock(); _mockLogger = new Mock>(); _messageService = new MessageCommandService( _mockMessagesRepo.Object, _mockUsersRepo.Object, _mockGroupsRepo.Object, _mockPrivateChatsRepo.Object, _mockUserPrivateChatCreator.Object, _mockVerifyFriendship.Object, _mockMediaService.Object, _mockLogger.Object); } // Test for SendMessageAsync action [Test] public async Task SendMessageAsync_ToUser_Success() { // Arrange var senderId = Guid.NewGuid(); var recipientId = Guid.NewGuid(); var privateChat = new PrivateChat { Id = recipientId, UserAId = senderId, UserBId = Guid.NewGuid() }; var sendParams = new SendMessage( "Hello", null, recipientId, RecipientType.User, senderId, DateTime.UtcNow, new List()); _mockPrivateChatsRepo .Setup(r => r.GetByIdAsync(recipientId)) .ReturnsAsync(privateChat); _mockMessagesRepo .Setup(r => r.AddAsync(It.IsAny())) .Returns(Task.CompletedTask); // Act var result = await _messageService.SendMessageAsync(sendParams); // Assert Assert.That(result.IsSuccess, Is.True); Assert.That(result.Exception, Is.Null); _mockMessagesRepo.Verify(r => r.AddAsync(It.Is(m => m.SenderId == senderId && m.RecipientId == recipientId && m.RecipientType == RecipientType.User && m.EncryptedContent == "Hello")), Times.Once); } [Test] public async Task SendMessageAsync_ToUser_When_AttachMediaThrowsException_ReturnsFailure() { // Arrange var senderId = Guid.NewGuid(); var recipientId = Guid.NewGuid(); var sendMediaId = Guid.NewGuid(); var privateChat = new PrivateChat { Id = recipientId, UserAId = senderId, UserBId = recipientId }; var sendParams = new SendMessage( "Hello", null, recipientId, RecipientType.User, senderId, DateTime.UtcNow, new List { new SendMedia(sendMediaId, string.Empty) }); _mockPrivateChatsRepo .Setup(r => r.GetByIdAsync(recipientId)) .ReturnsAsync(privateChat); _mockMediaService .Setup(m => m.AttachToMessageAsync(sendMediaId, It.IsAny())) .ThrowsAsync(new Exception("Unexpected DB error")); // Act var result = await _messageService.SendMessageAsync(sendParams); // Assert Assert.That(result.IsSuccess, Is.False); Assert.That(result.Exception!.Message, Is.EqualTo("Unexpected DB error")); _mockMessagesRepo.Verify(r => r.AddAsync(It.IsAny()), Times.Never); } [Test] public async Task SendMessageAsync_ToGroup_Success() { // Arrange var senderId = Guid.NewGuid(); var groupId = Guid.NewGuid(); var sendMessageParams = new SendMessage("Hello Group", null, groupId, RecipientType.Group, senderId, DateTime.UtcNow, new List()); _mockGroupsRepo.Setup(r => r.Exist(groupId)).Returns(true); _mockGroupsRepo.Setup(r => r.IsUserMemberOfGroupAsync(senderId, groupId)).ReturnsAsync(true); _mockMessagesRepo.Setup(r => r.AddAsync(It.IsAny())).Returns(Task.CompletedTask); // Act var result = await _messageService.SendMessageAsync(sendMessageParams); // Assert Assert.That(result, Is.Not.Null); Assert.That(result.IsSuccess, Is.True); Assert.That(result.Exception, Is.Null); _mockMessagesRepo.Verify(r => r.AddAsync(It.Is(m => m.RecipientId == groupId && m.RecipientType == RecipientType.Group)), Times.Once); } [Test] public async Task SendMessageAsync_ToUser_PrivateChatNotFound_ReturnsFailure() { // Arrange var senderId = Guid.NewGuid(); var recipientId = Guid.NewGuid(); var sendParams = new SendMessage( "Hello", null, recipientId, RecipientType.User, senderId, DateTime.UtcNow, new List()); _mockPrivateChatsRepo .Setup(r => r.GetByIdAsync(recipientId)) .ReturnsAsync((PrivateChat?)null); // Act var result = await _messageService.SendMessageAsync(sendParams); // Assert Assert.That(result.IsSuccess, Is.False); Assert.That(result.Exception, Is.TypeOf()); Assert.That(result.Message, Is.Null); } // Test for EditMessageAsync action [Test] public async Task EditMessageAsync_Success() { // Arrange var editorId = Guid.NewGuid(); var messageId = Guid.NewGuid(); var originalMessage = new Message { Id = messageId, SenderId = editorId, EncryptedContent = "Old", RecipientId = Guid.NewGuid(), RecipientType = RecipientType.User }; var editParams = new EditMessage(editorId, messageId, "New Content", DateTime.UtcNow); _mockMessagesRepo.Setup(r => r.FindByIdAsync(messageId)).ReturnsAsync(originalMessage); _mockMessagesRepo.Setup(r => r.UpdateAsync(It.IsAny())).Returns(Task.CompletedTask); // Act var result = await _messageService.EditMessageAsync(editParams); // Assert Assert.That(result, Is.Not.Null); Assert.That(result.IsSuccess, Is.True); Assert.That(result.OriginalMessage, Is.Not.Null); Assert.That(messageId, Is.EqualTo(result.OriginalMessage!.Id)); _mockMessagesRepo.Verify(r => r.UpdateAsync(It.Is(m => m.Id == messageId && m.EncryptedContent == "New Content" && m.IsEdited == true && m.EditedAt == editParams.EditedAt)), Times.Once); } [Test] public async Task EditMessageAsync_MessageNotFound_ReturnsFailure() { // Arrange var editorId = Guid.NewGuid(); var messageId = Guid.NewGuid(); var editParams = new EditMessage(editorId, messageId, "New Content", DateTime.UtcNow); _mockMessagesRepo.Setup(r => r.FindByIdAsync(messageId)). ThrowsAsync(new NotFoundByKeyException(messageId)); // Act var result = await _messageService.EditMessageAsync(editParams); // Assert Assert.That(result, Is.Not.Null); Assert.That(result.IsSuccess, Is.False); Assert.That(result.Exception, Is.Not.Null); Assert.That(result.Exception,Is.TypeOf>()); Assert.That(result.OriginalMessage, Is.Null); } [Test] public async Task EditMessageAsync_NotSender_ReturnsFailure() { // Arrange var editorId = Guid.NewGuid(); var senderId = Guid.NewGuid(); // Different from editorId var messageId = Guid.NewGuid(); var originalMessage = new Message { Id = messageId, SenderId = senderId, EncryptedContent = "Old" }; var editParams = new EditMessage(editorId, messageId, "New Content", DateTime.UtcNow); _mockMessagesRepo.Setup(r => r.FindByIdAsync(messageId)).ReturnsAsync(originalMessage); // Act var result = await _messageService.EditMessageAsync(editParams); // Assert Assert.That(result, Is.Not.Null); Assert.That(result.IsSuccess, Is.False); Assert.That(result.Exception, Is.Not.Null); Assert.That(result.Exception,Is.TypeOf()); Assert.That(result.OriginalMessage, Is.Null); } // Test for DeleteMessageAsync action [Test] public async Task DeleteMessageAsync_Success() { // Arrange var deleterId = Guid.NewGuid(); var messageId = Guid.NewGuid(); var originalMessage = new Message { Id = messageId, SenderId = deleterId, RecipientId = Guid.NewGuid(), RecipientType = RecipientType.User }; var deleteParams = new DeleteMessage(deleterId, messageId); _mockMessagesRepo.Setup(r => r.FindByIdAsync(messageId)).ReturnsAsync(originalMessage); _mockMessagesRepo.Setup(r => r.RemoveAsync(messageId)).Returns(Task.CompletedTask); // Act var result = await _messageService.DeleteMessageAsync(deleteParams); // Assert Assert.That(result, Is.Not.Null); Assert.That(result.IsSuccess, Is.True); Assert.That(result.OriginalMessage, Is.Not.Null); Assert.That(messageId, Is.EqualTo(result.OriginalMessage!.Id)); _mockMessagesRepo.Verify(r => r.RemoveAsync(messageId), Times.Once); } [Test] public async Task DeleteMessageAsync_MessageNotFound_ReturnsFailure() { // Arrange var deleterId = Guid.NewGuid(); var messageId = Guid.NewGuid(); var deleteParams = new DeleteMessage(deleterId, messageId); _mockMessagesRepo.Setup(r => r.FindByIdAsync(messageId)). ThrowsAsync(new NotFoundByKeyException(messageId)); // Act var result = await _messageService.DeleteMessageAsync(deleteParams); // Assert Assert.That(result, Is.Not.Null); Assert.That(result.IsSuccess, Is.False); Assert.That(result.Exception, Is.Not.Null); Assert.That(result.Exception,Is.TypeOf()); Assert.That(result.OriginalMessage, Is.Null); } [Test] public async Task DeleteMessageAsync_NotSender_ReturnsFailure() { // Arrange var deleterId = Guid.NewGuid(); var senderId = Guid.NewGuid(); // Different var messageId = Guid.NewGuid(); var originalMessage = new Message { Id = messageId, SenderId = senderId }; var deleteParams = new DeleteMessage(deleterId, messageId); _mockMessagesRepo.Setup(r => r.FindByIdAsync(messageId)).ReturnsAsync(originalMessage); // Act var result = await _messageService.DeleteMessageAsync(deleteParams); // Assert Assert.That(result, Is.Not.Null); Assert.That(result.IsSuccess, Is.False); Assert.That(result.Exception, Is.Not.Null); Assert.That(result.Exception,Is.TypeOf()); Assert.That(result.OriginalMessage, Is.Null); } }