Files
ChatBot/ChatBot.Tests/Data/Repositories/ChatSessionRepositoryTests.cs
Leonid Pershin 2a26e84100
All checks were successful
SonarQube / Build and analyze (push) Successful in 3m39s
add tests
2025-10-21 02:30:04 +03:00

495 lines
15 KiB
C#

using ChatBot.Data;
using ChatBot.Data.Interfaces;
using ChatBot.Data.Repositories;
using ChatBot.Tests.TestUtilities;
using FluentAssertions;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Moq;
namespace ChatBot.Tests.Data.Repositories;
public class ChatSessionRepositoryTests : TestBase
{
private ChatBotDbContext _dbContext = null!;
private ChatSessionRepository _repository = null!;
public ChatSessionRepositoryTests()
{
SetupServices();
}
protected override void ConfigureServices(IServiceCollection services)
{
// Add in-memory database with unique name per test
services.AddDbContext<ChatBotDbContext>(options =>
options.UseInMemoryDatabase(Guid.NewGuid().ToString())
);
// Add logger
services.AddSingleton(Mock.Of<ILogger<ChatSessionRepository>>());
// Add repository
services.AddScoped<IChatSessionRepository, ChatSessionRepository>();
}
protected override void SetupServices()
{
base.SetupServices();
_dbContext = ServiceProvider.GetRequiredService<ChatBotDbContext>();
_repository = (ChatSessionRepository)
ServiceProvider.GetRequiredService<IChatSessionRepository>();
// Ensure database is created
_dbContext.Database.EnsureCreated();
}
private void CleanupDatabase()
{
_dbContext.ChatSessions.RemoveRange(_dbContext.ChatSessions);
_dbContext.ChatMessages.RemoveRange(_dbContext.ChatMessages);
_dbContext.SaveChanges();
}
[Fact]
public async Task GetOrCreateAsync_ShouldReturnExistingSession_WhenSessionExists()
{
// Arrange
CleanupDatabase();
var chatId = 12345L;
var chatType = "private";
var chatTitle = "Test Chat";
var existingSession = TestDataBuilder.Mocks.CreateChatSessionEntity(
1,
chatId,
"existing-session",
chatType,
chatTitle
);
_dbContext.ChatSessions.Add(existingSession);
await _dbContext.SaveChangesAsync();
// Act
var result = await _repository.GetOrCreateAsync(chatId, chatType, chatTitle);
// Assert
result.Should().NotBeNull();
result.ChatId.Should().Be(chatId);
result.SessionId.Should().Be("existing-session");
}
[Fact]
public async Task GetOrCreateAsync_ShouldCreateNewSession_WhenSessionDoesNotExist()
{
// Arrange
CleanupDatabase();
var chatId = 12345L;
var chatType = "private";
var chatTitle = "Test Chat";
// Act
var result = await _repository.GetOrCreateAsync(chatId, chatType, chatTitle);
// Assert
result.Should().NotBeNull();
result.ChatId.Should().Be(chatId);
result.ChatType.Should().Be(chatType);
result.ChatTitle.Should().Be(chatTitle);
result.SessionId.Should().NotBeNullOrEmpty();
}
[Fact]
public async Task GetByChatIdAsync_ShouldReturnSession_WhenSessionExists()
{
// Arrange
CleanupDatabase();
var chatId = 12345L;
var session = TestDataBuilder.Mocks.CreateChatSessionEntity(1, chatId);
_dbContext.ChatSessions.Add(session);
await _dbContext.SaveChangesAsync();
// Act
var result = await _repository.GetByChatIdAsync(chatId);
// Assert
result.Should().NotBeNull();
result.ChatId.Should().Be(chatId);
}
[Fact]
public async Task GetByChatIdAsync_ShouldReturnNull_WhenSessionDoesNotExist()
{
// Arrange
CleanupDatabase();
var chatId = 12345L;
// Act
var result = await _repository.GetByChatIdAsync(chatId);
// Assert
result.Should().BeNull();
}
[Fact]
public async Task GetBySessionIdAsync_ShouldReturnSession_WhenSessionExists()
{
// Arrange
CleanupDatabase();
var sessionId = "test-session";
var session = TestDataBuilder.Mocks.CreateChatSessionEntity(1, 12345, sessionId);
_dbContext.ChatSessions.Add(session);
await _dbContext.SaveChangesAsync();
// Act
var result = await _repository.GetBySessionIdAsync(sessionId);
// Assert
result.Should().NotBeNull();
result.SessionId.Should().Be(sessionId);
}
[Fact]
public async Task GetBySessionIdAsync_ShouldReturnNull_WhenSessionDoesNotExist()
{
// Arrange
CleanupDatabase();
var sessionId = "nonexistent-session";
// Act
var result = await _repository.GetBySessionIdAsync(sessionId);
// Assert
result.Should().BeNull();
}
[Fact]
public async Task UpdateAsync_ShouldUpdateSession()
{
// Arrange
CleanupDatabase();
var session = TestDataBuilder.Mocks.CreateChatSessionEntity(1, 12345);
_dbContext.ChatSessions.Add(session);
await _dbContext.SaveChangesAsync();
session.ChatTitle = "Updated Title";
// Act
var result = await _repository.UpdateAsync(session);
// Assert
result.Should().NotBeNull();
result.ChatTitle.Should().Be("Updated Title");
}
[Fact]
public async Task DeleteAsync_ShouldReturnTrue_WhenSessionExists()
{
// Arrange
CleanupDatabase();
var chatId = 12345L;
var session = TestDataBuilder.Mocks.CreateChatSessionEntity(1, chatId);
_dbContext.ChatSessions.Add(session);
await _dbContext.SaveChangesAsync();
// Act
var result = await _repository.DeleteAsync(chatId);
// Assert
result.Should().BeTrue();
var deletedSession = await _repository.GetByChatIdAsync(chatId);
deletedSession.Should().BeNull();
}
[Fact]
public async Task DeleteAsync_ShouldReturnFalse_WhenSessionDoesNotExist()
{
// Arrange
CleanupDatabase();
var chatId = 12345L;
// Act
var result = await _repository.DeleteAsync(chatId);
// Assert
result.Should().BeFalse();
}
[Fact]
public async Task GetActiveSessionsCountAsync_ShouldReturnCorrectCount()
{
// Arrange
CleanupDatabase();
var session1 = TestDataBuilder.Mocks.CreateChatSessionEntity(1, 12345);
var session2 = TestDataBuilder.Mocks.CreateChatSessionEntity(2, 12346);
_dbContext.ChatSessions.AddRange(session1, session2);
await _dbContext.SaveChangesAsync();
// Act
var count = await _repository.GetActiveSessionsCountAsync();
// Assert
count.Should().Be(2);
}
[Fact]
public async Task CleanupOldSessionsAsync_ShouldRemoveOldSessions()
{
// Arrange
CleanupDatabase();
// Verify database is empty
var initialCount = await _repository.GetActiveSessionsCountAsync();
initialCount.Should().Be(0);
var oldSession = TestDataBuilder.Mocks.CreateChatSessionEntity(1, 12345);
oldSession.LastUpdatedAt = DateTime.UtcNow.AddDays(-2); // 2 days old
var recentSession = TestDataBuilder.Mocks.CreateChatSessionEntity(2, 12346);
recentSession.LastUpdatedAt = DateTime.UtcNow.AddMinutes(-30); // 30 minutes old
_dbContext.ChatSessions.AddRange(oldSession, recentSession);
await _dbContext.SaveChangesAsync();
// Act
var removedCount = await _repository.CleanupOldSessionsAsync(1); // Remove sessions older than 1 hour
// Assert
removedCount.Should().Be(1);
var remainingSessions = await _repository.GetActiveSessionsCountAsync();
remainingSessions.Should().Be(1);
}
[Fact]
public async Task GetMessagesAsync_ShouldReturnMessages_WhenMessagesExist()
{
// Arrange
CleanupDatabase();
var session = TestDataBuilder.Mocks.CreateChatSessionEntity(1, 12345);
_dbContext.ChatSessions.Add(session);
await _dbContext.SaveChangesAsync();
await _repository.AddMessageAsync(session.Id, "Message 1", "User", 0);
await _repository.AddMessageAsync(session.Id, "Message 2", "Assistant", 1);
// Act
var messages = await _repository.GetMessagesAsync(session.Id);
// Assert
messages.Should().HaveCount(2);
messages[0].Content.Should().Be("Message 1");
messages[0].Role.Should().Be("User");
messages[1].Content.Should().Be("Message 2");
messages[1].Role.Should().Be("Assistant");
}
[Fact]
public async Task GetMessagesAsync_ShouldReturnEmptyList_WhenNoMessages()
{
// Arrange
CleanupDatabase();
var session = TestDataBuilder.Mocks.CreateChatSessionEntity(1, 12345);
_dbContext.ChatSessions.Add(session);
await _dbContext.SaveChangesAsync();
// Act
var messages = await _repository.GetMessagesAsync(session.Id);
// Assert
messages.Should().BeEmpty();
}
[Fact]
public async Task AddMessageAsync_ShouldAddMessage()
{
// Arrange
CleanupDatabase();
var session = TestDataBuilder.Mocks.CreateChatSessionEntity(1, 12345);
_dbContext.ChatSessions.Add(session);
await _dbContext.SaveChangesAsync();
// Act
var message = await _repository.AddMessageAsync(session.Id, "Test message", "User", 0);
// Assert
message.Should().NotBeNull();
message.Content.Should().Be("Test message");
message.Role.Should().Be("User");
message.MessageOrder.Should().Be(0);
message.SessionId.Should().Be(session.Id);
var messages = await _repository.GetMessagesAsync(session.Id);
messages.Should().HaveCount(1);
}
[Fact]
public async Task ClearMessagesAsync_ShouldRemoveAllMessages()
{
// Arrange
CleanupDatabase();
var session = TestDataBuilder.Mocks.CreateChatSessionEntity(1, 12345);
_dbContext.ChatSessions.Add(session);
await _dbContext.SaveChangesAsync();
await _repository.AddMessageAsync(session.Id, "Message 1", "User", 0);
await _repository.AddMessageAsync(session.Id, "Message 2", "Assistant", 1);
await _repository.AddMessageAsync(session.Id, "Message 3", "User", 2);
// Act
await _repository.ClearMessagesAsync(session.Id);
// Assert
var messages = await _repository.GetMessagesAsync(session.Id);
messages.Should().BeEmpty();
}
[Fact]
public async Task GetSessionsForCleanupAsync_ShouldReturnOldSessions()
{
// Arrange
CleanupDatabase();
var oldSession1 = TestDataBuilder.Mocks.CreateChatSessionEntity(1, 12345);
oldSession1.LastUpdatedAt = DateTime.UtcNow.AddDays(-2);
var oldSession2 = TestDataBuilder.Mocks.CreateChatSessionEntity(2, 12346);
oldSession2.LastUpdatedAt = DateTime.UtcNow.AddHours(-25);
var recentSession = TestDataBuilder.Mocks.CreateChatSessionEntity(3, 12347);
recentSession.LastUpdatedAt = DateTime.UtcNow.AddMinutes(-30);
_dbContext.ChatSessions.AddRange(oldSession1, oldSession2, recentSession);
await _dbContext.SaveChangesAsync();
// Act
var sessionsForCleanup = await _repository.GetSessionsForCleanupAsync(24);
// Assert
sessionsForCleanup.Should().HaveCount(2);
sessionsForCleanup.Should().Contain(s => s.ChatId == 12345);
sessionsForCleanup.Should().Contain(s => s.ChatId == 12346);
sessionsForCleanup.Should().NotContain(s => s.ChatId == 12347);
}
[Fact]
public async Task GetSessionsForCleanupAsync_ShouldReturnEmptyList_WhenNoOldSessions()
{
// Arrange
CleanupDatabase();
var recentSession = TestDataBuilder.Mocks.CreateChatSessionEntity(1, 12345);
recentSession.LastUpdatedAt = DateTime.UtcNow.AddMinutes(-30);
_dbContext.ChatSessions.Add(recentSession);
await _dbContext.SaveChangesAsync();
// Act
var sessionsForCleanup = await _repository.GetSessionsForCleanupAsync(24);
// Assert
sessionsForCleanup.Should().BeEmpty();
}
[Fact]
public async Task UpdateAsync_ShouldUpdateLastUpdatedAt()
{
// Arrange
CleanupDatabase();
var session = TestDataBuilder.Mocks.CreateChatSessionEntity(1, 12345);
var originalLastUpdated = DateTime.UtcNow.AddDays(-1);
session.LastUpdatedAt = originalLastUpdated;
_dbContext.ChatSessions.Add(session);
await _dbContext.SaveChangesAsync();
// Act
session.Model = "new-model";
var updatedSession = await _repository.UpdateAsync(session);
// Assert
updatedSession.LastUpdatedAt.Should().BeAfter(originalLastUpdated);
updatedSession.Model.Should().Be("new-model");
}
[Fact]
public async Task GetByChatIdAsync_ShouldIncludeMessages()
{
// Arrange
CleanupDatabase();
var session = TestDataBuilder.Mocks.CreateChatSessionEntity(1, 12345);
_dbContext.ChatSessions.Add(session);
await _dbContext.SaveChangesAsync();
await _repository.AddMessageAsync(session.Id, "Test message", "User", 0);
// Act
var retrievedSession = await _repository.GetByChatIdAsync(12345);
// Assert
retrievedSession.Should().NotBeNull();
retrievedSession!.Messages.Should().HaveCount(1);
retrievedSession.Messages.First().Content.Should().Be("Test message");
}
[Fact]
public async Task GetBySessionIdAsync_ShouldIncludeMessages()
{
// Arrange
CleanupDatabase();
var sessionId = "test-session-id";
var session = TestDataBuilder.Mocks.CreateChatSessionEntity(1, 12345, sessionId);
_dbContext.ChatSessions.Add(session);
await _dbContext.SaveChangesAsync();
await _repository.AddMessageAsync(session.Id, "Test message", "User", 0);
// Act
var retrievedSession = await _repository.GetBySessionIdAsync(sessionId);
// Assert
retrievedSession.Should().NotBeNull();
retrievedSession!.Messages.Should().HaveCount(1);
}
[Fact]
public async Task AddMessageAsync_WithMultipleMessages_ShouldMaintainOrder()
{
// Arrange
CleanupDatabase();
var session = TestDataBuilder.Mocks.CreateChatSessionEntity(1, 12345);
_dbContext.ChatSessions.Add(session);
await _dbContext.SaveChangesAsync();
// Act
await _repository.AddMessageAsync(session.Id, "Message 1", "User", 0);
await _repository.AddMessageAsync(session.Id, "Message 2", "Assistant", 1);
await _repository.AddMessageAsync(session.Id, "Message 3", "User", 2);
// Assert
var messages = await _repository.GetMessagesAsync(session.Id);
messages.Should().HaveCount(3);
messages[0].MessageOrder.Should().Be(0);
messages[1].MessageOrder.Should().Be(1);
messages[2].MessageOrder.Should().Be(2);
}
[Fact]
public async Task CleanupOldSessionsAsync_WithNoOldSessions_ShouldReturnZero()
{
// Arrange
CleanupDatabase();
var recentSession = TestDataBuilder.Mocks.CreateChatSessionEntity(1, 12345);
recentSession.LastUpdatedAt = DateTime.UtcNow.AddMinutes(-10);
_dbContext.ChatSessions.Add(recentSession);
await _dbContext.SaveChangesAsync();
// Act
var removedCount = await _repository.CleanupOldSessionsAsync(24);
// Assert
removedCount.Should().Be(0);
}
}