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); // GetOrCreateAsync method var getOrCreateMethod = methods.FirstOrDefault(m => m.Name == "GetOrCreateAsync"); getOrCreateMethod.Should().NotBeNull(); getOrCreateMethod!.ReturnType.Should().Be(typeof(Task)); getOrCreateMethod.GetParameters().Should().HaveCount(3); getOrCreateMethod.GetParameters()[0].ParameterType.Should().Be(); getOrCreateMethod.GetParameters()[1].ParameterType.Should().Be(); getOrCreateMethod.GetParameters()[2].ParameterType.Should().Be(); // GetAsync method var getMethod = methods.FirstOrDefault(m => m.Name == "GetAsync"); getMethod.Should().NotBeNull(); getMethod!.ReturnType.Should().Be(typeof(Task)); getMethod.GetParameters().Should().HaveCount(1); getMethod.GetParameters()[0].ParameterType.Should().Be(); // RemoveAsync method var removeMethod = methods.FirstOrDefault(m => m.Name == "RemoveAsync"); removeMethod.Should().NotBeNull(); removeMethod!.ReturnType.Should().Be(typeof(Task)); removeMethod.GetParameters().Should().HaveCount(1); removeMethod.GetParameters()[0].ParameterType.Should().Be(); // GetActiveSessionsCountAsync method var getActiveSessionsCountMethod = methods.FirstOrDefault(m => m.Name == "GetActiveSessionsCountAsync" ); getActiveSessionsCountMethod.Should().NotBeNull(); getActiveSessionsCountMethod!.ReturnType.Should().Be(typeof(Task)); getActiveSessionsCountMethod.GetParameters().Should().BeEmpty(); // CleanupOldSessionsAsync method var cleanupOldSessionsMethod = methods.FirstOrDefault(m => m.Name == "CleanupOldSessionsAsync"); cleanupOldSessionsMethod.Should().NotBeNull(); cleanupOldSessionsMethod!.ReturnType.Should().Be(typeof(Task)); cleanupOldSessionsMethod.GetParameters().Should().HaveCount(1); cleanupOldSessionsMethod.GetParameters()[0].ParameterType.Should().Be(); // SaveSessionAsync method var saveSessionAsyncMethod = methods.FirstOrDefault(m => m.Name == "SaveSessionAsync"); saveSessionAsyncMethod.Should().NotBeNull(); saveSessionAsyncMethod!.ReturnType.Should().Be(); saveSessionAsyncMethod.GetParameters().Should().HaveCount(1); saveSessionAsyncMethod.GetParameters()[0].ParameterType.Should().Be(); } [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 async Task ISessionStorage_GetOrCreateAsync_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.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 ISessionStorage_GetAsync_ShouldReturnChatSessionOrNull() { // Arrange var mock = new Mock(); var chatId = 12345L; var expectedSession = TestDataBuilder.ChatSessions.CreateBasicSession(chatId, "private"); mock.Setup(x => x.GetAsync(It.IsAny())).ReturnsAsync(expectedSession); // Act var result = await mock.Object.GetAsync(chatId); // Assert result.Should().Be(expectedSession); mock.Verify(x => x.GetAsync(chatId), Times.Once); } [Fact] public async Task ISessionStorage_GetAsync_ShouldReturnNullWhenSessionNotFound() { // Arrange var mock = new Mock(); var chatId = 12345L; mock.Setup(x => x.GetAsync(It.IsAny())).ReturnsAsync((ChatSession?)null); // Act var result = await mock.Object.GetAsync(chatId); // Assert result.Should().BeNull(); mock.Verify(x => x.GetAsync(chatId), Times.Once); } [Fact] public async Task ISessionStorage_RemoveAsync_ShouldReturnBoolean() { // Arrange var mock = new Mock(); var chatId = 12345L; var expectedResult = true; mock.Setup(x => x.RemoveAsync(It.IsAny())).ReturnsAsync(expectedResult); // Act var result = await mock.Object.RemoveAsync(chatId); // Assert result.Should().Be(expectedResult); mock.Verify(x => x.RemoveAsync(chatId), Times.Once); } [Fact] public async Task ISessionStorage_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 ISessionStorage_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 ISessionStorage_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); // 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 async Task ISessionStorage_GetOrCreateAsync_ShouldUseDefaultValues() { // Arrange var mock = new Mock(); var chatId = 12345L; var expectedSession = TestDataBuilder.ChatSessions.CreateBasicSession(chatId, "private"); 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); // 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(); // GetOrCreateAsync should have default parameters var getOrCreateMethod = methods.First(m => m.Name == "GetOrCreateAsync"); 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(""); // CleanupOldSessionsAsync should have default parameter var cleanupMethod = methods.First(m => m.Name == "CleanupOldSessionsAsync"); cleanupMethod.GetParameters()[0].HasDefaultValue.Should().BeTrue(); cleanupMethod.GetParameters()[0].DefaultValue.Should().Be(24); } }