using ChatBot.Models; using ChatBot.Models.Configuration; using ChatBot.Models.Dto; using ChatBot.Models.Entities; using ChatBot.Services.Interfaces; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Moq; using OllamaSharp.Models.Chat; using Telegram.Bot; namespace ChatBot.Tests.TestUtilities; /// /// Builder pattern for creating test data and mocks /// public static class TestDataBuilder { public static class ChatSessions { public static ChatSession CreateBasicSession( long chatId = 12345, string chatType = "private" ) { return new ChatSession { ChatId = chatId, ChatType = chatType, ChatTitle = chatType == "private" ? "" : "Test Group", Model = "llama3.2", CreatedAt = DateTime.UtcNow.AddHours(-1), LastUpdatedAt = DateTime.UtcNow, }; } public static ChatSession CreateSessionWithMessages( long chatId = 12345, int messageCount = 3 ) { var session = CreateBasicSession(chatId); for (int i = 0; i < messageCount; i++) { session.AddUserMessage($"Test message {i + 1}", "testuser"); session.AddAssistantMessage($"AI response {i + 1}"); } return session; } } public static class ChatMessages { public static ChatMessage CreateUserMessage( string content = "Hello", string username = "testuser" ) { return new ChatMessage { Role = ChatRole.User, Content = content }; } public static ChatMessage CreateAssistantMessage( string content = "Hello! How can I help you?" ) { return new ChatMessage { Role = ChatRole.Assistant, Content = content }; } public static ChatMessage CreateSystemMessage( string content = "You are a helpful assistant." ) { return new ChatMessage { Role = ChatRole.System, Content = content }; } public static List CreateMessageHistory(int count = 5) { var messages = new List(); for (int i = 0; i < count; i++) { messages.Add(CreateUserMessage($"User message {i + 1}")); messages.Add(CreateAssistantMessage($"Assistant response {i + 1}")); } return messages; } } public static class Configurations { public static AISettings CreateAISettings() { return new AISettings { Temperature = 0.7, MaxRetryAttempts = 3, RetryDelayMs = 1000, MaxRetryDelayMs = 10000, EnableExponentialBackoff = true, RequestTimeoutSeconds = 30, EnableHistoryCompression = true, CompressionThreshold = 10, CompressionTarget = 5, MinMessageLengthForSummarization = 50, MaxSummarizedMessageLength = 200, CompressionTimeoutSeconds = 15, }; } public static OllamaSettings CreateOllamaSettings() { return new OllamaSettings { Url = "http://localhost:11434", DefaultModel = "llama3.2" }; } public static TelegramBotSettings CreateTelegramBotSettings() { return new TelegramBotSettings { BotToken = "test-bot-token" }; } public static DatabaseSettings CreateDatabaseSettings() { return new DatabaseSettings { ConnectionString = "Host=localhost;Port=5432;Database=test_chatbot;Username=test;Password=test", CommandTimeout = 30, EnableSensitiveDataLogging = false, }; } } public static class Mocks { public static Mock> CreateLoggerMock() { return new Mock>(); } public static Mock> CreateOptionsMock(T value) where T : class { var mock = new Mock>(); mock.Setup(x => x.Value).Returns(value); return mock; } public static Mock CreateSessionStorageMock() { var mock = new Mock(); var sessions = new Dictionary(); mock.Setup(x => x.GetOrCreate(It.IsAny(), It.IsAny(), It.IsAny())) .Returns( (chatId, chatType, chatTitle) => { if (!sessions.ContainsKey(chatId)) { var session = TestDataBuilder.ChatSessions.CreateBasicSession( chatId, chatType ); session.ChatTitle = chatTitle; sessions[chatId] = session; } return sessions[chatId]; } ); mock.Setup(x => x.Get(It.IsAny())) .Returns(chatId => sessions.TryGetValue(chatId, out var session) ? session : null ); mock.Setup(x => x.SaveSessionAsync(It.IsAny())) .Returns(session => { sessions[session.ChatId] = session; return Task.CompletedTask; }); mock.Setup(x => x.Remove(It.IsAny())) .Returns(chatId => sessions.Remove(chatId)); mock.Setup(x => x.GetActiveSessionsCount()).Returns(() => sessions.Count); mock.Setup(x => x.CleanupOldSessions(It.IsAny())).Returns(hoursOld => 0); return mock; } public static Mock CreateAIServiceMock() { var mock = new Mock(); mock.Setup(x => x.GenerateChatCompletionAsync( It.IsAny>(), It.IsAny() ) ) .ReturnsAsync("Test AI response"); mock.Setup(x => x.GenerateChatCompletionWithCompressionAsync( It.IsAny>(), It.IsAny() ) ) .ReturnsAsync("Test AI response with compression"); return mock; } public static Mock CreateCompressionServiceMock() { var mock = new Mock(); mock.Setup(x => x.ShouldCompress(It.IsAny(), It.IsAny())) .Returns((count, threshold) => count > threshold); mock.Setup(x => x.CompressHistoryAsync( It.IsAny>(), It.IsAny(), It.IsAny() ) ) .ReturnsAsync( (List messages, int targetCount, CancellationToken ct) => { // Simple compression: take last targetCount messages return messages.TakeLast(targetCount).ToList(); } ); return mock; } public static Mock CreateOllamaClientMock() { var mock = new Mock(); mock.Setup(x => x.ChatAsync(It.IsAny())) .Returns( TestDataBuilder.Mocks.CreateAsyncEnumerable( new List() ) ); return mock; } /// /// Create a mock chat session entity /// public static ChatSessionEntity CreateChatSessionEntity( int id = 1, long chatId = 12345, string sessionId = "test-session", string chatType = "private", string chatTitle = "Test Chat" ) { return new ChatSessionEntity { Id = id, ChatId = chatId, SessionId = sessionId, ChatType = chatType, ChatTitle = chatTitle, CreatedAt = DateTime.UtcNow, LastUpdatedAt = DateTime.UtcNow, Messages = new List(), }; } /// /// Create a mock chat message entity /// public static ChatMessageEntity CreateChatMessageEntity( int id = 1, int sessionId = 1, string content = "Test message", string role = "user", int messageOrder = 1 ) { return new ChatMessageEntity { Id = id, SessionId = sessionId, Content = content, Role = role, MessageOrder = messageOrder, CreatedAt = DateTime.UtcNow, }; } /// /// Create a mock Telegram bot client /// public static Mock CreateTelegramBotClient() { var mock = new Mock(); return mock; } /// /// Create a mock Telegram bot user /// public static global::Telegram.Bot.Types.User CreateTelegramBot() { return new global::Telegram.Bot.Types.User { Id = 12345, Username = "test_bot", FirstName = "Test Bot", }; } /// /// Create async enumerable from list /// public static async IAsyncEnumerable CreateAsyncEnumerable(IEnumerable items) { foreach (var item in items) { yield return item; } await Task.CompletedTask; } } }