DeutschLernen/GermanApp/Infrastructure/Data/DbContext/AppDbContext.cs
Lasse Rune Hansen 6bcf592918 feat(backend): complete unit tests for User Authentication feature
- Fix MSTest compatibility with .NET 9.0 by upgrading to MSTest.TestFramework 4.2.3
- Move Tests directory to solution level (Tests/) to prevent test files from being compiled with GermanApp
- Update test project references to point to GermanApp/GermanApp.csproj
- Add InternalsVisibleTo attributes for test assemblies
- Make RefreshToken properties internal for testability
- Fix User.ChangeEmail null handling
- Add 46 comprehensive unit tests for User and RefreshToken domain entities
- All tests passing successfully

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-06-05 17:07:15 +02:00

91 lines
4 KiB
C#

using GermanApp.Domain.Entities;
using Microsoft.EntityFrameworkCore;
namespace GermanApp.Infrastructure.Data.DbContext;
/// <summary>
/// Entity Framework Core database context.
/// This is part of the Infrastructure layer.
/// </summary>
public class AppDbContext : Microsoft.EntityFrameworkCore.DbContext
{
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options)
{
}
// DbSets for domain entities
public DbSet<Lesson> Lessons { get; set; } = null!;
public DbSet<User> Users { get; set; } = null!;
public DbSet<RefreshToken> RefreshTokens { get; set; } = null!;
// Note: Value objects are not stored directly as entities.
// They are owned by entities and stored as part of the entity's data.
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
// Configure Lesson entity
modelBuilder.Entity<Lesson>(builder =>
{
builder.HasKey(l => l.Id);
builder.Property(l => l.Title).IsRequired().HasMaxLength(200);
builder.Property(l => l.Description).IsRequired().HasMaxLength(2000);
builder.Property(l => l.Level).IsRequired();
builder.Property(l => l.CreatedAt).IsRequired();
builder.Property(l => l.UpdatedAt).IsRequired(false);
// Value object: GermanWord would be configured as an owned entity
// builder.OwnsMany(l => l.Words, wordBuilder =>
// {
// wordBuilder.Property(w => w.Value).HasColumnName("WordValue");
// wordBuilder.Property(w => w.Translation).HasColumnName("Translation");
// wordBuilder.Property(w => w.Article).HasColumnName("Article");
// wordBuilder.Property(w => w.PartOfSpeech).HasColumnName("PartOfSpeech");
// });
});
// Configure User entity
modelBuilder.Entity<User>(builder =>
{
builder.HasKey(u => u.Id);
builder.Property(u => u.Username).IsRequired().HasMaxLength(50);
builder.Property(u => u.Email).IsRequired().HasMaxLength(100);
builder.Property(u => u.PasswordHash).IsRequired().HasMaxLength(255);
builder.Property(u => u.CurrentLevel).HasMaxLength(10).HasDefaultValue("A1");
builder.Property(u => u.Streak).HasDefaultValue(0);
builder.Property(u => u.TotalPoints).HasDefaultValue(0);
builder.Property(u => u.CreatedAt).IsRequired();
// Ensure unique constraints
builder.HasIndex(u => u.Username).IsUnique();
builder.HasIndex(u => u.Email).IsUnique();
});
// Configure RefreshToken entity
modelBuilder.Entity<RefreshToken>(builder =>
{
builder.HasKey(r => r.Id);
builder.Property(r => r.UserId).IsRequired();
builder.Property(r => r.Token).IsRequired().HasMaxLength(255);
builder.Property(r => r.ExpiresAt).IsRequired();
builder.Property(r => r.IsActive).HasDefaultValue(true);
builder.Property(r => r.CreatedAt).IsRequired();
builder.Property(r => r.RevokedAt).IsRequired(false);
// Foreign key to User
builder.HasOne<User>()
.WithMany()
.HasForeignKey(r => r.UserId)
.OnDelete(DeleteBehavior.Cascade);
});
// Seed data (optional) - Note: For EF Core, we need to set properties directly
// In a real application, use migrations or a separate seeding mechanism
// modelBuilder.Entity<Lesson>().HasData(
// new { Id = 1, Title = "Greetings", Description = "Basic German greetings", Level = 1, CreatedAt = DateTime.UtcNow },
// new { Id = 2, Title = "Numbers", Description = "German numbers 1-100", Level = 1, CreatedAt = DateTime.UtcNow },
// new { Id = 3, Title = "Grammar Basics", Description = "Basic German grammar", Level = 2, CreatedAt = DateTime.UtcNow }
// );
}
}