using ChatBot.Models; using ChatBot.Services; using ChatBot.Services.Interfaces; using ChatBot.Tests.TestUtilities; using FluentAssertions; using Moq; namespace ChatBot.Tests.Services.Interfaces; public class ISessionStorageTests : UnitTestBase { [Fact] public void ISessionStorage_ShouldHaveCorrectMethodSignatures() { // Arrange & Act var interfaceType = typeof(ISessionStorage); var methods = interfaceType.GetMethods(); // Assert methods.Should().HaveCount(6); // GetOrCreate method var getOrCreateMethod = methods.FirstOrDefault(m => m.Name == "GetOrCreate"); getOrCreateMethod.Should().NotBeNull(); getOrCreateMethod!.ReturnType.Should().Be(typeof(ChatSession)); getOrCreateMethod.GetParameters().Should().HaveCount(3); getOrCreateMethod.GetParameters()[0].ParameterType.Should().Be(typeof(long)); getOrCreateMethod.GetParameters()[1].ParameterType.Should().Be(typeof(string)); getOrCreateMethod.GetParameters()[2].ParameterType.Should().Be(typeof(string)); // Get method var getMethod = methods.FirstOrDefault(m => m.Name == "Get"); getMethod.Should().NotBeNull(); getMethod!.ReturnType.Should().Be(typeof(ChatSession)); getMethod.GetParameters().Should().HaveCount(1); getMethod.GetParameters()[0].ParameterType.Should().Be(typeof(long)); // Remove method var removeMethod = methods.FirstOrDefault(m => m.Name == "Remove"); removeMethod.Should().NotBeNull(); removeMethod!.ReturnType.Should().Be(typeof(bool)); removeMethod.GetParameters().Should().HaveCount(1); removeMethod.GetParameters()[0].ParameterType.Should().Be(typeof(long)); // GetActiveSessionsCount method var getActiveSessionsCountMethod = methods.FirstOrDefault(m => m.Name == "GetActiveSessionsCount" ); getActiveSessionsCountMethod.Should().NotBeNull(); getActiveSessionsCountMethod!.ReturnType.Should().Be(typeof(int)); getActiveSessionsCountMethod.GetParameters().Should().BeEmpty(); // CleanupOldSessions method var cleanupOldSessionsMethod = methods.FirstOrDefault(m => m.Name == "CleanupOldSessions"); cleanupOldSessionsMethod.Should().NotBeNull(); cleanupOldSessionsMethod!.ReturnType.Should().Be(typeof(int)); cleanupOldSessionsMethod.GetParameters().Should().HaveCount(1); cleanupOldSessionsMethod.GetParameters()[0].ParameterType.Should().Be(typeof(int)); // SaveSessionAsync method var saveSessionAsyncMethod = methods.FirstOrDefault(m => m.Name == "SaveSessionAsync"); saveSessionAsyncMethod.Should().NotBeNull(); saveSessionAsyncMethod!.ReturnType.Should().Be(typeof(Task)); saveSessionAsyncMethod.GetParameters().Should().HaveCount(1); saveSessionAsyncMethod.GetParameters()[0].ParameterType.Should().Be(typeof(ChatSession)); } [Fact] public void ISessionStorage_ShouldBeImplementedByDatabaseSessionStorage() { // Arrange & Act var databaseSessionStorageType = typeof(DatabaseSessionStorage); var interfaceType = typeof(ISessionStorage); // Assert interfaceType.IsAssignableFrom(databaseSessionStorageType).Should().BeTrue(); } [Fact] public void ISessionStorage_ShouldBeImplementedByInMemorySessionStorage() { // Arrange & Act var inMemorySessionStorageType = typeof(InMemorySessionStorage); var interfaceType = typeof(ISessionStorage); // Assert interfaceType.IsAssignableFrom(inMemorySessionStorageType).Should().BeTrue(); } [Fact] public void ISessionStorage_GetOrCreate_ShouldReturnChatSession() { // Arrange var mock = new Mock(); var chatId = 12345L; var chatType = "private"; var chatTitle = "Test Chat"; var expectedSession = TestDataBuilder.ChatSessions.CreateBasicSession(chatId, chatType); mock.Setup(x => x.GetOrCreate(It.IsAny(), It.IsAny(), It.IsAny())) .Returns(expectedSession); // Act var result = mock.Object.GetOrCreate(chatId, chatType, chatTitle); // Assert result.Should().Be(expectedSession); mock.Verify(x => x.GetOrCreate(chatId, chatType, chatTitle), Times.Once); } [Fact] public void ISessionStorage_Get_ShouldReturnChatSessionOrNull() { // Arrange var mock = new Mock(); var chatId = 12345L; var expectedSession = TestDataBuilder.ChatSessions.CreateBasicSession(chatId, "private"); mock.Setup(x => x.Get(It.IsAny())).Returns(expectedSession); // Act var result = mock.Object.Get(chatId); // Assert result.Should().Be(expectedSession); mock.Verify(x => x.Get(chatId), Times.Once); } [Fact] public void ISessionStorage_Get_ShouldReturnNullWhenSessionNotFound() { // Arrange var mock = new Mock(); var chatId = 12345L; mock.Setup(x => x.Get(It.IsAny())).Returns((ChatSession?)null); // Act var result = mock.Object.Get(chatId); // Assert result.Should().BeNull(); mock.Verify(x => x.Get(chatId), Times.Once); } [Fact] public void ISessionStorage_Remove_ShouldReturnBoolean() { // Arrange var mock = new Mock(); var chatId = 12345L; var expectedResult = true; mock.Setup(x => x.Remove(It.IsAny())).Returns(expectedResult); // Act var result = mock.Object.Remove(chatId); // Assert result.Should().Be(expectedResult); mock.Verify(x => x.Remove(chatId), Times.Once); } [Fact] public void ISessionStorage_GetActiveSessionsCount_ShouldReturnInt() { // Arrange var mock = new Mock(); var expectedCount = 5; mock.Setup(x => x.GetActiveSessionsCount()).Returns(expectedCount); // Act var result = mock.Object.GetActiveSessionsCount(); // Assert result.Should().Be(expectedCount); mock.Verify(x => x.GetActiveSessionsCount(), Times.Once); } [Fact] public void ISessionStorage_CleanupOldSessions_ShouldReturnInt() { // Arrange var mock = new Mock(); var hoursOld = 24; var expectedCleanedCount = 3; mock.Setup(x => x.CleanupOldSessions(It.IsAny())).Returns(expectedCleanedCount); // Act var result = mock.Object.CleanupOldSessions(hoursOld); // Assert result.Should().Be(expectedCleanedCount); mock.Verify(x => x.CleanupOldSessions(hoursOld), Times.Once); } [Fact] public void ISessionStorage_CleanupOldSessions_ShouldUseDefaultValue() { // Arrange var mock = new Mock(); var expectedCleanedCount = 2; mock.Setup(x => x.CleanupOldSessions(It.IsAny())).Returns(expectedCleanedCount); // Act var result = mock.Object.CleanupOldSessions(); // Assert result.Should().Be(expectedCleanedCount); mock.Verify(x => x.CleanupOldSessions(24), Times.Once); // Default value is 24 } [Fact] public async Task ISessionStorage_SaveSessionAsync_ShouldReturnTask() { // Arrange var mock = new Mock(); var session = TestDataBuilder.ChatSessions.CreateBasicSession(12345L, "private"); mock.Setup(x => x.SaveSessionAsync(It.IsAny())).Returns(Task.CompletedTask); // Act await mock.Object.SaveSessionAsync(session); // Assert mock.Verify(x => x.SaveSessionAsync(session), Times.Once); } [Fact] public void ISessionStorage_GetOrCreate_ShouldUseDefaultValues() { // Arrange var mock = new Mock(); var chatId = 12345L; var expectedSession = TestDataBuilder.ChatSessions.CreateBasicSession(chatId, "private"); mock.Setup(x => x.GetOrCreate(It.IsAny(), It.IsAny(), It.IsAny())) .Returns(expectedSession); // Act var result = mock.Object.GetOrCreate(chatId); // Assert result.Should().Be(expectedSession); mock.Verify(x => x.GetOrCreate(chatId, "private", ""), Times.Once); // Default values } [Fact] public void ISessionStorage_ShouldBePublicInterface() { // Arrange & Act var interfaceType = typeof(ISessionStorage); // Assert interfaceType.IsPublic.Should().BeTrue(); interfaceType.IsInterface.Should().BeTrue(); } [Fact] public void ISessionStorage_ShouldHaveCorrectNamespace() { // Arrange & Act var interfaceType = typeof(ISessionStorage); // Assert interfaceType.Namespace.Should().Be("ChatBot.Services.Interfaces"); } [Fact] public void ISessionStorage_ShouldHaveCorrectGenericConstraints() { // Arrange & Act var interfaceType = typeof(ISessionStorage); var methods = interfaceType.GetMethods(); // Assert // All methods should be public methods.All(m => m.IsPublic).Should().BeTrue(); // GetOrCreate should have default parameters var getOrCreateMethod = methods.First(m => m.Name == "GetOrCreate"); getOrCreateMethod.GetParameters()[1].HasDefaultValue.Should().BeTrue(); getOrCreateMethod.GetParameters()[1].DefaultValue.Should().Be("private"); getOrCreateMethod.GetParameters()[2].HasDefaultValue.Should().BeTrue(); getOrCreateMethod.GetParameters()[2].DefaultValue.Should().Be(""); // CleanupOldSessions should have default parameter var cleanupMethod = methods.First(m => m.Name == "CleanupOldSessions"); cleanupMethod.GetParameters()[0].HasDefaultValue.Should().BeTrue(); cleanupMethod.GetParameters()[0].DefaultValue.Should().Be(24); } }