using ChatBot.Data.Interfaces; using ChatBot.Data.Repositories; using ChatBot.Models.Entities; using ChatBot.Tests.TestUtilities; using FluentAssertions; using Moq; namespace ChatBot.Tests.Data.Interfaces; public class IChatSessionRepositoryTests : UnitTestBase { [Fact] public void IChatSessionRepository_ShouldHaveCorrectMethodSignatures() { // Arrange & Act var interfaceType = typeof(IChatSessionRepository); var methods = interfaceType.GetMethods(); // Assert methods.Should().HaveCount(11); // GetOrCreateAsync method var getOrCreateAsyncMethod = methods.FirstOrDefault(m => m.Name == "GetOrCreateAsync"); getOrCreateAsyncMethod.Should().NotBeNull(); getOrCreateAsyncMethod!.ReturnType.Should().Be>(); getOrCreateAsyncMethod.GetParameters().Should().HaveCount(3); getOrCreateAsyncMethod.GetParameters()[0].ParameterType.Should().Be(); getOrCreateAsyncMethod.GetParameters()[1].ParameterType.Should().Be(); getOrCreateAsyncMethod.GetParameters()[2].ParameterType.Should().Be(); // GetByChatIdAsync method var getByChatIdAsyncMethod = methods.FirstOrDefault(m => m.Name == "GetByChatIdAsync"); getByChatIdAsyncMethod.Should().NotBeNull(); getByChatIdAsyncMethod!.ReturnType.Should().Be>(); getByChatIdAsyncMethod.GetParameters().Should().HaveCount(1); getByChatIdAsyncMethod.GetParameters()[0].ParameterType.Should().Be(); // GetBySessionIdAsync method var getBySessionIdAsyncMethod = methods.FirstOrDefault(m => m.Name == "GetBySessionIdAsync" ); getBySessionIdAsyncMethod.Should().NotBeNull(); getBySessionIdAsyncMethod!.ReturnType.Should().Be>(); getBySessionIdAsyncMethod.GetParameters().Should().HaveCount(1); getBySessionIdAsyncMethod.GetParameters()[0].ParameterType.Should().Be(); // UpdateAsync method var updateAsyncMethod = methods.FirstOrDefault(m => m.Name == "UpdateAsync"); updateAsyncMethod.Should().NotBeNull(); updateAsyncMethod!.ReturnType.Should().Be>(); updateAsyncMethod.GetParameters().Should().HaveCount(1); updateAsyncMethod.GetParameters()[0].ParameterType.Should().Be(); // DeleteAsync method var deleteAsyncMethod = methods.FirstOrDefault(m => m.Name == "DeleteAsync"); deleteAsyncMethod.Should().NotBeNull(); deleteAsyncMethod!.ReturnType.Should().Be>(); deleteAsyncMethod.GetParameters().Should().HaveCount(1); deleteAsyncMethod.GetParameters()[0].ParameterType.Should().Be(); // GetMessagesAsync method var getMessagesAsyncMethod = methods.FirstOrDefault(m => m.Name == "GetMessagesAsync"); getMessagesAsyncMethod.Should().NotBeNull(); getMessagesAsyncMethod!.ReturnType.Should().Be>>(); getMessagesAsyncMethod.GetParameters().Should().HaveCount(1); getMessagesAsyncMethod.GetParameters()[0].ParameterType.Should().Be(); // AddMessageAsync method var addMessageAsyncMethod = methods.FirstOrDefault(m => m.Name == "AddMessageAsync"); addMessageAsyncMethod.Should().NotBeNull(); addMessageAsyncMethod!.ReturnType.Should().Be>(); addMessageAsyncMethod.GetParameters().Should().HaveCount(4); addMessageAsyncMethod.GetParameters()[0].ParameterType.Should().Be(); addMessageAsyncMethod.GetParameters()[1].ParameterType.Should().Be(); addMessageAsyncMethod.GetParameters()[2].ParameterType.Should().Be(); addMessageAsyncMethod.GetParameters()[3].ParameterType.Should().Be(); // ClearMessagesAsync method var clearMessagesAsyncMethod = methods.FirstOrDefault(m => m.Name == "ClearMessagesAsync"); clearMessagesAsyncMethod.Should().NotBeNull(); clearMessagesAsyncMethod!.ReturnType.Should().Be(); clearMessagesAsyncMethod.GetParameters().Should().HaveCount(1); clearMessagesAsyncMethod.GetParameters()[0].ParameterType.Should().Be(); // GetActiveSessionsCountAsync method var getActiveSessionsCountAsyncMethod = methods.FirstOrDefault(m => m.Name == "GetActiveSessionsCountAsync" ); getActiveSessionsCountAsyncMethod.Should().NotBeNull(); getActiveSessionsCountAsyncMethod!.ReturnType.Should().Be>(); getActiveSessionsCountAsyncMethod.GetParameters().Should().BeEmpty(); // CleanupOldSessionsAsync method var cleanupOldSessionsAsyncMethod = methods.FirstOrDefault(m => m.Name == "CleanupOldSessionsAsync" ); cleanupOldSessionsAsyncMethod.Should().NotBeNull(); cleanupOldSessionsAsyncMethod!.ReturnType.Should().Be>(); cleanupOldSessionsAsyncMethod.GetParameters().Should().HaveCount(1); cleanupOldSessionsAsyncMethod.GetParameters()[0].ParameterType.Should().Be(); // GetSessionsForCleanupAsync method var getSessionsForCleanupAsyncMethod = methods.FirstOrDefault(m => m.Name == "GetSessionsForCleanupAsync" ); getSessionsForCleanupAsyncMethod.Should().NotBeNull(); getSessionsForCleanupAsyncMethod!.ReturnType.Should().Be>>(); getSessionsForCleanupAsyncMethod.GetParameters().Should().HaveCount(1); getSessionsForCleanupAsyncMethod.GetParameters()[0].ParameterType.Should().Be(); } [Fact] public void IChatSessionRepository_ShouldBeImplementedByChatSessionRepository() { // Arrange & Act var chatSessionRepositoryType = typeof(ChatSessionRepository); var interfaceType = typeof(IChatSessionRepository); // Assert interfaceType.IsAssignableFrom(chatSessionRepositoryType).Should().BeTrue(); } [Fact] public async Task IChatSessionRepository_GetOrCreateAsync_ShouldReturnChatSessionEntity() { // Arrange var mock = new Mock(); var chatId = 12345L; var chatType = "private"; var chatTitle = "Test Chat"; var expectedSession = TestDataBuilder.Mocks.CreateChatSessionEntity(); mock.Setup(x => x.GetOrCreateAsync(It.IsAny(), It.IsAny(), It.IsAny()) ) .ReturnsAsync(expectedSession); // Act var result = await mock.Object.GetOrCreateAsync(chatId, chatType, chatTitle); // Assert result.Should().Be(expectedSession); mock.Verify(x => x.GetOrCreateAsync(chatId, chatType, chatTitle), Times.Once); } [Fact] public async Task IChatSessionRepository_GetOrCreateAsync_ShouldUseDefaultValues() { // Arrange var mock = new Mock(); var chatId = 12345L; var expectedSession = TestDataBuilder.Mocks.CreateChatSessionEntity(); mock.Setup(x => x.GetOrCreateAsync(It.IsAny(), It.IsAny(), It.IsAny()) ) .ReturnsAsync(expectedSession); // Act var result = await mock.Object.GetOrCreateAsync(chatId); // Assert result.Should().Be(expectedSession); mock.Verify(x => x.GetOrCreateAsync(chatId, "private", ""), Times.Once); } [Fact] public async Task IChatSessionRepository_GetByChatIdAsync_ShouldReturnChatSessionEntityOrNull() { // Arrange var mock = new Mock(); var chatId = 12345L; var expectedSession = TestDataBuilder.Mocks.CreateChatSessionEntity(); mock.Setup(x => x.GetByChatIdAsync(It.IsAny())).ReturnsAsync(expectedSession); // Act var result = await mock.Object.GetByChatIdAsync(chatId); // Assert result.Should().Be(expectedSession); mock.Verify(x => x.GetByChatIdAsync(chatId), Times.Once); } [Fact] public async Task IChatSessionRepository_GetByChatIdAsync_ShouldReturnNullWhenNotFound() { // Arrange var mock = new Mock(); var chatId = 12345L; mock.Setup(x => x.GetByChatIdAsync(It.IsAny())) .ReturnsAsync((ChatSessionEntity?)null); // Act var result = await mock.Object.GetByChatIdAsync(chatId); // Assert result.Should().BeNull(); mock.Verify(x => x.GetByChatIdAsync(chatId), Times.Once); } [Fact] public async Task IChatSessionRepository_GetBySessionIdAsync_ShouldReturnChatSessionEntityOrNull() { // Arrange var mock = new Mock(); var sessionId = "test-session-id"; var expectedSession = TestDataBuilder.Mocks.CreateChatSessionEntity(); mock.Setup(x => x.GetBySessionIdAsync(It.IsAny())).ReturnsAsync(expectedSession); // Act var result = await mock.Object.GetBySessionIdAsync(sessionId); // Assert result.Should().Be(expectedSession); mock.Verify(x => x.GetBySessionIdAsync(sessionId), Times.Once); } [Fact] public async Task IChatSessionRepository_UpdateAsync_ShouldReturnUpdatedChatSessionEntity() { // Arrange var mock = new Mock(); var session = TestDataBuilder.Mocks.CreateChatSessionEntity(); var expectedUpdatedSession = TestDataBuilder.Mocks.CreateChatSessionEntity(); mock.Setup(x => x.UpdateAsync(It.IsAny())) .ReturnsAsync(expectedUpdatedSession); // Act var result = await mock.Object.UpdateAsync(session); // Assert result.Should().Be(expectedUpdatedSession); mock.Verify(x => x.UpdateAsync(session), Times.Once); } [Fact] public async Task IChatSessionRepository_DeleteAsync_ShouldReturnBoolean() { // Arrange var mock = new Mock(); var chatId = 12345L; var expectedResult = true; mock.Setup(x => x.DeleteAsync(It.IsAny())).ReturnsAsync(expectedResult); // Act var result = await mock.Object.DeleteAsync(chatId); // Assert result.Should().Be(expectedResult); mock.Verify(x => x.DeleteAsync(chatId), Times.Once); } [Fact] public async Task IChatSessionRepository_GetMessagesAsync_ShouldReturnListOfMessages() { // Arrange var mock = new Mock(); var sessionId = 1; var expectedMessages = new List { TestDataBuilder.Mocks.CreateChatMessageEntity(), TestDataBuilder.Mocks.CreateChatMessageEntity(), }; mock.Setup(x => x.GetMessagesAsync(It.IsAny())).ReturnsAsync(expectedMessages); // Act var result = await mock.Object.GetMessagesAsync(sessionId); // Assert result.Should().BeEquivalentTo(expectedMessages); mock.Verify(x => x.GetMessagesAsync(sessionId), Times.Once); } [Fact] public async Task IChatSessionRepository_AddMessageAsync_ShouldReturnChatMessageEntity() { // Arrange var mock = new Mock(); var sessionId = 1; var content = "Test message"; var role = "user"; var messageOrder = 1; var expectedMessage = TestDataBuilder.Mocks.CreateChatMessageEntity(); mock.Setup(x => x.AddMessageAsync( It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny() ) ) .ReturnsAsync(expectedMessage); // Act var result = await mock.Object.AddMessageAsync(sessionId, content, role, messageOrder); // Assert result.Should().Be(expectedMessage); mock.Verify(x => x.AddMessageAsync(sessionId, content, role, messageOrder), Times.Once); } [Fact] public async Task IChatSessionRepository_ClearMessagesAsync_ShouldReturnTask() { // Arrange var mock = new Mock(); var sessionId = 1; mock.Setup(x => x.ClearMessagesAsync(It.IsAny())).Returns(Task.CompletedTask); // Act await mock.Object.ClearMessagesAsync(sessionId); // Assert mock.Verify(x => x.ClearMessagesAsync(sessionId), Times.Once); } [Fact] public async Task IChatSessionRepository_GetActiveSessionsCountAsync_ShouldReturnInt() { // Arrange var mock = new Mock(); var expectedCount = 5; mock.Setup(x => x.GetActiveSessionsCountAsync()).ReturnsAsync(expectedCount); // Act var result = await mock.Object.GetActiveSessionsCountAsync(); // Assert result.Should().Be(expectedCount); mock.Verify(x => x.GetActiveSessionsCountAsync(), Times.Once); } [Fact] public async Task IChatSessionRepository_CleanupOldSessionsAsync_ShouldReturnInt() { // Arrange var mock = new Mock(); var hoursOld = 24; var expectedCleanedCount = 3; mock.Setup(x => x.CleanupOldSessionsAsync(It.IsAny())) .ReturnsAsync(expectedCleanedCount); // Act var result = await mock.Object.CleanupOldSessionsAsync(hoursOld); // Assert result.Should().Be(expectedCleanedCount); mock.Verify(x => x.CleanupOldSessionsAsync(hoursOld), Times.Once); } [Fact] public async Task IChatSessionRepository_CleanupOldSessionsAsync_ShouldUseDefaultValue() { // Arrange var mock = new Mock(); var expectedCleanedCount = 2; mock.Setup(x => x.CleanupOldSessionsAsync(It.IsAny())) .ReturnsAsync(expectedCleanedCount); // Act var result = await mock.Object.CleanupOldSessionsAsync(); // Assert result.Should().Be(expectedCleanedCount); mock.Verify(x => x.CleanupOldSessionsAsync(24), Times.Once); } [Fact] public async Task IChatSessionRepository_GetSessionsForCleanupAsync_ShouldReturnListOfSessions() { // Arrange var mock = new Mock(); var hoursOld = 24; var expectedSessions = new List { TestDataBuilder.Mocks.CreateChatSessionEntity(), TestDataBuilder.Mocks.CreateChatSessionEntity(), }; mock.Setup(x => x.GetSessionsForCleanupAsync(It.IsAny())) .ReturnsAsync(expectedSessions); // Act var result = await mock.Object.GetSessionsForCleanupAsync(hoursOld); // Assert result.Should().BeEquivalentTo(expectedSessions); mock.Verify(x => x.GetSessionsForCleanupAsync(hoursOld), Times.Once); } [Fact] public async Task IChatSessionRepository_GetSessionsForCleanupAsync_ShouldUseDefaultValue() { // Arrange var mock = new Mock(); var expectedSessions = new List(); mock.Setup(x => x.GetSessionsForCleanupAsync(It.IsAny())) .ReturnsAsync(expectedSessions); // Act var result = await mock.Object.GetSessionsForCleanupAsync(); // Assert result.Should().BeEquivalentTo(expectedSessions); mock.Verify(x => x.GetSessionsForCleanupAsync(24), Times.Once); } [Fact] public void IChatSessionRepository_ShouldBePublicInterface() { // Arrange & Act var interfaceType = typeof(IChatSessionRepository); // Assert interfaceType.IsPublic.Should().BeTrue(); interfaceType.IsInterface.Should().BeTrue(); } [Fact] public void IChatSessionRepository_ShouldHaveCorrectNamespace() { // Arrange & Act var interfaceType = typeof(IChatSessionRepository); // Assert interfaceType.Namespace.Should().Be("ChatBot.Data.Interfaces"); } [Fact] public void IChatSessionRepository_ShouldHaveCorrectGenericConstraints() { // Arrange & Act var interfaceType = typeof(IChatSessionRepository); var methods = interfaceType.GetMethods(); // Assert // All methods should be public methods.All(m => m.IsPublic).Should().BeTrue(); // GetOrCreateAsync should have default parameters var getOrCreateAsyncMethod = methods.First(m => m.Name == "GetOrCreateAsync"); getOrCreateAsyncMethod.GetParameters()[1].HasDefaultValue.Should().BeTrue(); getOrCreateAsyncMethod.GetParameters()[1].DefaultValue.Should().Be("private"); getOrCreateAsyncMethod.GetParameters()[2].HasDefaultValue.Should().BeTrue(); getOrCreateAsyncMethod.GetParameters()[2].DefaultValue.Should().Be(""); // CleanupOldSessionsAsync should have default parameter var cleanupOldSessionsAsyncMethod = methods.First(m => m.Name == "CleanupOldSessionsAsync"); cleanupOldSessionsAsyncMethod.GetParameters()[0].HasDefaultValue.Should().BeTrue(); cleanupOldSessionsAsyncMethod.GetParameters()[0].DefaultValue.Should().Be(24); // GetSessionsForCleanupAsync should have default parameter var getSessionsForCleanupAsyncMethod = methods.First(m => m.Name == "GetSessionsForCleanupAsync" ); getSessionsForCleanupAsyncMethod.GetParameters()[0].HasDefaultValue.Should().BeTrue(); getSessionsForCleanupAsyncMethod.GetParameters()[0].DefaultValue.Should().Be(24); } }