using ChatBot.Services; using ChatBot.Services.Interfaces; using ChatBot.Tests.TestUtilities; using FluentAssertions; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Moq; using OllamaSharp.Models.Chat; namespace ChatBot.Tests.Integration; public class ChatServiceIntegrationTests : TestBase { private ChatService _chatService = null!; private Mock _sessionStorageMock = null!; private Mock _aiServiceMock = null!; public ChatServiceIntegrationTests() { SetupServices(); } protected override void ConfigureServices(IServiceCollection services) { // Add mocked services _sessionStorageMock = TestDataBuilder.Mocks.CreateSessionStorageMock(); _aiServiceMock = TestDataBuilder.Mocks.CreateAIServiceMock(); services.AddSingleton(_sessionStorageMock.Object); services.AddSingleton(_aiServiceMock.Object); services.AddSingleton(Mock.Of>()); services.AddSingleton( TestDataBuilder .Mocks.CreateOptionsMock(TestDataBuilder.Configurations.CreateAISettings()) .Object ); services.AddSingleton(TestDataBuilder.Mocks.CreateCompressionServiceMock().Object); services.AddScoped(); } protected override void SetupServices() { base.SetupServices(); _chatService = ServiceProvider.GetRequiredService(); } [Fact] public async Task ProcessMessageAsync_ShouldProcessUserMessage_WhenSessionExists() { // Arrange var chatId = 12345L; var username = "testuser"; var message = "Hello, how are you?"; var expectedResponse = "I'm doing well, thank you!"; var session = TestDataBuilder.ChatSessions.CreateBasicSession(chatId); _sessionStorageMock.Setup(x => x.GetOrCreate(chatId, "private", "")).Returns(session); _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); session.GetAllMessages().Should().HaveCount(2); // User message + AI response session.GetAllMessages()[0].Content.Should().Be(message); session.GetAllMessages()[0].Role.Should().Be(ChatRole.User); session.GetAllMessages()[1].Content.Should().Be(expectedResponse); session.GetAllMessages()[1].Role.Should().Be(ChatRole.Assistant); _sessionStorageMock.Verify(x => x.SaveSessionAsync(session), Times.Exactly(2)); } [Fact] public async Task ProcessMessageAsync_ShouldCreateNewSession_WhenSessionDoesNotExist() { // Arrange var chatId = 12345L; var username = "testuser"; var message = "Hello"; var expectedResponse = "Hi there!"; _sessionStorageMock .Setup(x => x.GetOrCreate(chatId, "private", "")) .Returns(TestDataBuilder.ChatSessions.CreateBasicSession(chatId)); _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.GetOrCreate(chatId, "private", ""), Times.Once); _sessionStorageMock.Verify( x => x.SaveSessionAsync(It.IsAny()), Times.Exactly(2) ); } [Fact] public async Task ProcessMessageAsync_ShouldHandleEmptyMessage() { // Arrange var chatId = 12345L; var username = "testuser"; var message = ""; var expectedResponse = "I didn't receive a message. Could you please try again?"; var session = TestDataBuilder.ChatSessions.CreateBasicSession(chatId); _sessionStorageMock.Setup(x => x.GetOrCreate(chatId, "private", "")).Returns(session); _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); session.GetAllMessages().Should().HaveCount(2); } [Fact] public async Task ProcessMessageAsync_ShouldHandleAIServiceException() { // Arrange var chatId = 12345L; var username = "testuser"; var message = "Hello"; var session = TestDataBuilder.ChatSessions.CreateBasicSession(chatId); _sessionStorageMock.Setup(x => x.GetOrCreate(chatId, "private", "")).Returns(session); _aiServiceMock .Setup(x => x.GenerateChatCompletionWithCompressionAsync( It.IsAny>(), It.IsAny() ) ) .ThrowsAsync(new Exception("AI service error")); // Act var result = await _chatService.ProcessMessageAsync(chatId, username, message); // Assert - should return error message instead of throwing result.Should().Contain("ошибка"); } [Fact] public async Task ProcessMessageAsync_ShouldUseCompression_WhenEnabled() { // Arrange var chatId = 12345L; var username = "testuser"; var message = "Hello"; var expectedResponse = "Hi there!"; var session = TestDataBuilder.ChatSessions.CreateSessionWithMessages(chatId, 10); // 10 messages _sessionStorageMock.Setup(x => x.GetOrCreate(chatId, "private", "")).Returns(session); _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); _aiServiceMock.Verify( x => x.GenerateChatCompletionWithCompressionAsync( It.IsAny>(), It.IsAny() ), Times.Once ); } [Fact] public async Task ClearHistoryAsync_ShouldClearSessionMessages() { // 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.GetAllMessages().Should().BeEmpty(); _sessionStorageMock.Verify(x => x.SaveSessionAsync(session), Times.Once); } [Fact] public async Task ClearHistoryAsync_ShouldHandleNonExistentSession() { // Arrange var chatId = 12345L; _sessionStorageMock.Setup(x => x.Get(chatId)).Returns((ChatBot.Models.ChatSession?)null); // Act await _chatService.ClearHistoryAsync(chatId); // Assert _sessionStorageMock.Verify( x => x.SaveSessionAsync(It.IsAny()), Times.Never ); } }