using ChatBot.Models; using ChatBot.Models.Configuration; using ChatBot.Models.Dto; using ChatBot.Services; using ChatBot.Services.Interfaces; using ChatBot.Tests.TestUtilities; using FluentAssertions; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Moq; namespace ChatBot.Tests.Services; public class ChatServiceTests : UnitTestBase { private readonly Mock> _loggerMock; private readonly Mock _aiServiceMock; private readonly Mock _sessionStorageMock; private readonly Mock _compressionServiceMock; private readonly AISettings _aiSettings; private readonly ChatService _chatService; public ChatServiceTests() { _loggerMock = TestDataBuilder.Mocks.CreateLoggerMock(); _aiServiceMock = TestDataBuilder.Mocks.CreateAIServiceMock(); _sessionStorageMock = TestDataBuilder.Mocks.CreateSessionStorageMock(); _compressionServiceMock = TestDataBuilder.Mocks.CreateCompressionServiceMock(); _aiSettings = TestDataBuilder.Configurations.CreateAISettings(); var optionsMock = TestDataBuilder.Mocks.CreateOptionsMock(_aiSettings); _chatService = new ChatService( _loggerMock.Object, _aiServiceMock.Object, _sessionStorageMock.Object, optionsMock.Object, _compressionServiceMock.Object ); } [Fact] public void GetOrCreateSession_ShouldCreateNewSession_WhenSessionDoesNotExist() { // Arrange var chatId = 12345L; var chatType = "private"; var chatTitle = "Test Chat"; // Act var session = _chatService.GetOrCreateSession(chatId, chatType, chatTitle); // Assert session.Should().NotBeNull(); session.ChatId.Should().Be(chatId); session.ChatType.Should().Be(chatType); session.ChatTitle.Should().Be(chatTitle); _sessionStorageMock.Verify(x => x.GetOrCreate(chatId, chatType, chatTitle), Times.Once); } [Fact] public void GetOrCreateSession_ShouldSetCompressionService_WhenCompressionIsEnabled() { // Arrange var chatId = 12345L; _aiSettings.EnableHistoryCompression = true; // Act var session = _chatService.GetOrCreateSession(chatId); // Assert session.Should().NotBeNull(); _sessionStorageMock.Verify(x => x.GetOrCreate(chatId, "private", ""), Times.Once); } [Fact] public async Task ProcessMessageAsync_ShouldProcessMessageSuccessfully_WhenValidInput() { // Arrange var chatId = 12345L; var username = "testuser"; var message = "Hello, bot!"; var expectedResponse = "Hello! How can I help you?"; _aiServiceMock .Setup(x => x.GenerateChatCompletionWithCompressionAsync( It.IsAny>(), It.IsAny() ) ) .ReturnsAsync(expectedResponse); // Act var result = await _chatService.ProcessMessageAsync(chatId, username, message); // Assert result.Should().Be(expectedResponse); _sessionStorageMock.Verify( x => x.SaveSessionAsync(It.IsAny()), Times.AtLeastOnce ); _aiServiceMock.Verify( x => x.GenerateChatCompletionWithCompressionAsync( It.IsAny>(), It.IsAny() ), Times.Once ); } [Fact] public async Task ProcessMessageAsync_ShouldReturnEmptyString_WhenAIResponseIsEmptyMarker() { // Arrange var chatId = 12345L; var username = "testuser"; var message = "Hello, bot!"; var emptyResponse = "{empty}"; _aiServiceMock .Setup(x => x.GenerateChatCompletionWithCompressionAsync( It.IsAny>(), It.IsAny() ) ) .ReturnsAsync(emptyResponse); // Act var result = await _chatService.ProcessMessageAsync(chatId, username, message); // Assert result.Should().BeEmpty(); } [Fact] public async Task ProcessMessageAsync_ShouldReturnErrorMessage_WhenAIResponseIsNull() { // Arrange var chatId = 12345L; var username = "testuser"; var message = "Hello, bot!"; _aiServiceMock .Setup(x => x.GenerateChatCompletionWithCompressionAsync( It.IsAny>(), It.IsAny() ) ) .ReturnsAsync((string)null!); // Act var result = await _chatService.ProcessMessageAsync(chatId, username, message); // Assert result.Should().Be("Извините, произошла ошибка при генерации ответа."); } [Fact] public async Task ProcessMessageAsync_ShouldHandleException_WhenErrorOccurs() { // Arrange var chatId = 12345L; var username = "testuser"; var message = "Hello, bot!"; _aiServiceMock .Setup(x => x.GenerateChatCompletionWithCompressionAsync( It.IsAny>(), It.IsAny() ) ) .ThrowsAsync(new Exception("Test exception")); // Act var result = await _chatService.ProcessMessageAsync(chatId, username, message); // Assert result.Should().Be("Извините, произошла ошибка при обработке вашего сообщения."); // Verify that error was logged // In a real test, we would verify the logger calls } [Fact] public async Task UpdateSessionParametersAsync_ShouldUpdateSession_WhenSessionExists() { // Arrange var chatId = 12345L; var newModel = "llama3.2"; var session = TestDataBuilder.ChatSessions.CreateBasicSession(chatId); _sessionStorageMock.Setup(x => x.Get(chatId)).Returns(session); // Act await _chatService.UpdateSessionParametersAsync(chatId, newModel); // Assert session.Model.Should().Be(newModel); _sessionStorageMock.Verify(x => x.SaveSessionAsync(session), Times.Once); } [Fact] public async Task UpdateSessionParametersAsync_ShouldNotUpdate_WhenSessionDoesNotExist() { // Arrange var chatId = 12345L; var newModel = "llama3.2"; _sessionStorageMock.Setup(x => x.Get(chatId)).Returns((ChatBot.Models.ChatSession?)null); // Act await _chatService.UpdateSessionParametersAsync(chatId, newModel); // Assert _sessionStorageMock.Verify( x => x.SaveSessionAsync(It.IsAny()), Times.Never ); } [Fact] public async Task ClearHistoryAsync_ShouldClearHistory_WhenSessionExists() { // Arrange var chatId = 12345L; var session = TestDataBuilder.ChatSessions.CreateSessionWithMessages(chatId, 5); _sessionStorageMock.Setup(x => x.Get(chatId)).Returns(session); // Act await _chatService.ClearHistoryAsync(chatId); // Assert session.GetMessageCount().Should().Be(0); _sessionStorageMock.Verify(x => x.SaveSessionAsync(session), Times.Once); } [Fact] public void GetSession_ShouldReturnSession_WhenSessionExists() { // Arrange var chatId = 12345L; var session = TestDataBuilder.ChatSessions.CreateBasicSession(chatId); _sessionStorageMock.Setup(x => x.Get(chatId)).Returns(session); // Act var result = _chatService.GetSession(chatId); // Assert result.Should().Be(session); } [Fact] public void GetSession_ShouldReturnNull_WhenSessionDoesNotExist() { // Arrange var chatId = 12345L; _sessionStorageMock.Setup(x => x.Get(chatId)).Returns((ChatBot.Models.ChatSession?)null); // Act var result = _chatService.GetSession(chatId); // Assert result.Should().BeNull(); } [Fact] public void RemoveSession_ShouldReturnTrue_WhenSessionExists() { // Arrange var chatId = 12345L; _sessionStorageMock.Setup(x => x.Remove(chatId)).Returns(true); // Act var result = _chatService.RemoveSession(chatId); // Assert result.Should().BeTrue(); _sessionStorageMock.Verify(x => x.Remove(chatId), Times.Once); } [Fact] public void GetActiveSessionsCount_ShouldReturnCorrectCount() { // Arrange var expectedCount = 5; _sessionStorageMock.Setup(x => x.GetActiveSessionsCount()).Returns(expectedCount); // Act var result = _chatService.GetActiveSessionsCount(); // Assert result.Should().Be(expectedCount); } [Fact] public void CleanupOldSessions_ShouldReturnCleanedCount() { // Arrange var hoursOld = 24; var expectedCleaned = 3; _sessionStorageMock.Setup(x => x.CleanupOldSessions(hoursOld)).Returns(expectedCleaned); // Act var result = _chatService.CleanupOldSessions(hoursOld); // Assert result.Should().Be(expectedCleaned); _sessionStorageMock.Verify(x => x.CleanupOldSessions(hoursOld), Times.Once); } }