Files
ChatBot/ChatBot.Tests/Data/MigrationsTests.cs
Leonid Pershin 1d0ebfeeb7
Some checks failed
SonarQube / Build and analyze (push) Failing after 1m44s
Unit Tests / Run Tests (push) Failing after 1m7s
fix tests
2025-10-20 10:39:58 +03:00

336 lines
11 KiB
C#

using ChatBot.Data;
using ChatBot.Migrations;
using FluentAssertions;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
namespace ChatBot.Tests.Data;
public class MigrationsTests : IDisposable
{
private readonly ServiceProvider _serviceProvider;
private readonly ChatBotDbContext _dbContext;
public MigrationsTests()
{
var services = new ServiceCollection();
// Add in-memory database with unique name per test
services.AddDbContext<ChatBotDbContext>(options =>
options.UseInMemoryDatabase(Guid.NewGuid().ToString())
);
_serviceProvider = services.BuildServiceProvider();
_dbContext = _serviceProvider.GetRequiredService<ChatBotDbContext>();
}
[Fact]
public void InitialCreateMigration_ShouldHaveCorrectName()
{
// Arrange
var migration = new InitialCreate();
// Assert
migration.Should().NotBeNull();
migration.GetType().Name.Should().Be("InitialCreate");
}
[Fact]
public void InitialCreateMigration_ShouldInheritFromMigration()
{
// Arrange
var migration = new InitialCreate();
// Assert
migration.Should().BeAssignableTo<Microsoft.EntityFrameworkCore.Migrations.Migration>();
}
[Fact]
public void InitialCreateMigration_ShouldBeInstantiable()
{
// Arrange & Act
var migration = new InitialCreate();
// Assert
migration.Should().NotBeNull();
}
[Fact]
public void InitialCreateMigration_ShouldHaveCorrectConstants()
{
// Arrange
var migration = new InitialCreate();
// Act & Assert
// Use reflection to access private constants
var migrationType = typeof(InitialCreate);
var chatSessionsTableNameField = migrationType.GetField(
"ChatSessionsTableName",
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static
);
chatSessionsTableNameField.Should().NotBeNull();
chatSessionsTableNameField!.GetValue(null).Should().Be("chat_sessions");
var chatMessagesTableNameField = migrationType.GetField(
"ChatMessagesTableName",
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static
);
chatMessagesTableNameField.Should().NotBeNull();
chatMessagesTableNameField!.GetValue(null).Should().Be("chat_messages");
var chatSessionsIdColumnField = migrationType.GetField(
"ChatSessionsIdColumn",
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static
);
chatSessionsIdColumnField.Should().NotBeNull();
chatSessionsIdColumnField!.GetValue(null).Should().Be("id");
var chatMessagesSessionIdColumnField = migrationType.GetField(
"ChatMessagesSessionIdColumn",
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static
);
chatMessagesSessionIdColumnField.Should().NotBeNull();
chatMessagesSessionIdColumnField!.GetValue(null).Should().Be("session_id");
var integerTypeField = migrationType.GetField(
"IntegerType",
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static
);
integerTypeField.Should().NotBeNull();
integerTypeField!.GetValue(null).Should().Be("integer");
}
[Fact]
public async Task InitialCreateMigration_ShouldApplySuccessfullyToDatabase()
{
// Arrange
var options = new DbContextOptionsBuilder<ChatBotDbContext>()
.UseInMemoryDatabase(Guid.NewGuid().ToString())
.Options;
using var context = new ChatBotDbContext(options);
// Act
await context.Database.EnsureCreatedAsync();
// Assert
var canConnect = await context.Database.CanConnectAsync();
canConnect.Should().BeTrue();
// Verify tables exist by trying to query them
var sessions = await context.ChatSessions.ToListAsync();
var messages = await context.ChatMessages.ToListAsync();
sessions.Should().NotBeNull();
messages.Should().NotBeNull();
}
[Fact]
public async Task InitialCreateMigration_ShouldCreateCorrectTableStructure()
{
// Arrange
var options = new DbContextOptionsBuilder<ChatBotDbContext>()
.UseInMemoryDatabase(Guid.NewGuid().ToString())
.Options;
using var context = new ChatBotDbContext(options);
// Act
await context.Database.EnsureCreatedAsync();
// Assert
var model = context.Model;
// Check chat_sessions entity
var chatSessionEntity = model.FindEntityType(
typeof(ChatBot.Models.Entities.ChatSessionEntity)
);
chatSessionEntity.Should().NotBeNull();
chatSessionEntity!.GetTableName().Should().Be("chat_sessions");
// Check chat_messages entity
var chatMessageEntity = model.FindEntityType(
typeof(ChatBot.Models.Entities.ChatMessageEntity)
);
chatMessageEntity.Should().NotBeNull();
chatMessageEntity!.GetTableName().Should().Be("chat_messages");
// Check foreign key relationship
var foreignKeys = chatMessageEntity.GetForeignKeys();
foreignKeys.Should().HaveCount(1);
var foreignKey = foreignKeys[0];
foreignKey.PrincipalEntityType.Should().Be(chatSessionEntity);
foreignKey.Properties.Should().HaveCount(1);
foreignKey.Properties[0].Name.Should().Be("SessionId");
foreignKey.DeleteBehavior.Should().Be(DeleteBehavior.Cascade);
}
[Fact]
public async Task InitialCreateMigration_ShouldCreateIndexes()
{
// Arrange
var options = new DbContextOptionsBuilder<ChatBotDbContext>()
.UseInMemoryDatabase(Guid.NewGuid().ToString())
.Options;
using var context = new ChatBotDbContext(options);
// Act
await context.Database.EnsureCreatedAsync();
// Assert
var model = context.Model;
// Check chat_sessions entity indexes
var chatSessionEntity = model.FindEntityType(
typeof(ChatBot.Models.Entities.ChatSessionEntity)
);
chatSessionEntity.Should().NotBeNull();
var sessionIndexes = chatSessionEntity!.GetIndexes().ToList();
sessionIndexes.Should().NotBeEmpty();
// Check chat_messages entity indexes
var chatMessageEntity = model.FindEntityType(
typeof(ChatBot.Models.Entities.ChatMessageEntity)
);
chatMessageEntity.Should().NotBeNull();
var messageIndexes = chatMessageEntity!.GetIndexes().ToList();
messageIndexes.Should().NotBeEmpty();
}
[Fact]
public async Task InitialCreateMigration_ShouldCreateUniqueConstraintOnSessionId()
{
// Arrange
var options = new DbContextOptionsBuilder<ChatBotDbContext>()
.UseInMemoryDatabase(Guid.NewGuid().ToString())
.Options;
using var context = new ChatBotDbContext(options);
// Act
await context.Database.EnsureCreatedAsync();
// Assert
var model = context.Model;
// Check chat_sessions entity has unique index on SessionId
var chatSessionEntity = model.FindEntityType(
typeof(ChatBot.Models.Entities.ChatSessionEntity)
);
chatSessionEntity.Should().NotBeNull();
var sessionIdProperty = chatSessionEntity!.FindProperty("SessionId");
sessionIdProperty.Should().NotBeNull();
var uniqueIndexes = chatSessionEntity
.GetIndexes()
.Where(i => i.IsUnique && i.Properties.Contains(sessionIdProperty))
.ToList();
uniqueIndexes.Should().NotBeEmpty();
}
[Fact]
public async Task InitialCreateMigration_ShouldCreateCompositeIndexOnSessionIdAndMessageOrder()
{
// Arrange
var options = new DbContextOptionsBuilder<ChatBotDbContext>()
.UseInMemoryDatabase(Guid.NewGuid().ToString())
.Options;
using var context = new ChatBotDbContext(options);
// Act
await context.Database.EnsureCreatedAsync();
// Assert
var model = context.Model;
// Check chat_messages entity has composite index
var chatMessageEntity = model.FindEntityType(
typeof(ChatBot.Models.Entities.ChatMessageEntity)
);
chatMessageEntity.Should().NotBeNull();
var sessionIdProperty = chatMessageEntity!.FindProperty("SessionId");
var messageOrderProperty = chatMessageEntity.FindProperty("MessageOrder");
sessionIdProperty.Should().NotBeNull();
messageOrderProperty.Should().NotBeNull();
var compositeIndexes = chatMessageEntity
.GetIndexes()
.Where(i =>
i.Properties.Count == 2
&& i.Properties.Contains(sessionIdProperty)
&& i.Properties.Contains(messageOrderProperty)
)
.ToList();
compositeIndexes.Should().NotBeEmpty();
}
[Fact]
public async Task InitialCreateMigration_ShouldSupportCascadeDelete()
{
// Arrange
var options = new DbContextOptionsBuilder<ChatBotDbContext>()
.UseInMemoryDatabase(Guid.NewGuid().ToString())
.Options;
using var context = new ChatBotDbContext(options);
// Act
await context.Database.EnsureCreatedAsync();
// Create test data
var session = new ChatBot.Models.Entities.ChatSessionEntity
{
SessionId = "test-session",
ChatId = 12345L,
ChatType = "private",
CreatedAt = DateTime.UtcNow,
LastUpdatedAt = DateTime.UtcNow,
};
context.ChatSessions.Add(session);
await context.SaveChangesAsync();
var message = new ChatBot.Models.Entities.ChatMessageEntity
{
SessionId = session.Id,
Content = "Test message",
Role = "user",
CreatedAt = DateTime.UtcNow,
MessageOrder = 1,
};
context.ChatMessages.Add(message);
await context.SaveChangesAsync();
// Verify data exists
var messageCount = await context.ChatMessages.CountAsync();
messageCount.Should().Be(1);
// Test cascade delete
context.ChatSessions.Remove(session);
await context.SaveChangesAsync();
// Assert - message should be deleted due to cascade
var remainingMessageCount = await context.ChatMessages.CountAsync();
remainingMessageCount.Should().Be(0);
}
public void Dispose()
{
_dbContext?.Dispose();
_serviceProvider?.Dispose();
GC.SuppressFinalize(this);
}
}