add latest tests
This commit is contained in:
334
ChatBot.Tests/Data/MigrationsTests.cs
Normal file
334
ChatBot.Tests/Data/MigrationsTests.cs
Normal file
@@ -0,0 +1,334 @@
|
||||
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.First();
|
||||
foreignKey.PrincipalEntityType.Should().Be(chatSessionEntity);
|
||||
foreignKey.Properties.Should().HaveCount(1);
|
||||
foreignKey.Properties.First().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();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user