DeutschLernen/Tests/Unit/Infrastructure/Data/Repositories/StoryRepositoryTests.cs
Mistral Vibe 01f6a1fd30 test(backend): add Phase 3 unit tests for Story Integration
- StoryServiceTests.cs: 536 lines, comprehensive tests for StoryService
- StoryGenerationServiceTests.cs: 469 lines, tests for AI story generation
- StoryUnlockServiceTests.cs: 292 lines, tests for story unlock logic
- StoryRepositoryTests.cs: 120 lines, tests for EF Core repository
- StoryProgressRepositoryTests.cs: 74 lines, tests for progress repository
- AppDbContext.cs: Made DbSet properties virtual for Moq compatibility
- Fixed return types in StoryRepository and StoryProgressRepository
- Updated docs/features/story-integration.md for Phase 3 completion
- All 324 unit tests pass

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-06-13 14:23:54 +02:00

120 lines
4.4 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using GermanApp.Domain.Entities;
using GermanApp.Infrastructure.Data.DbContext;
using GermanApp.Infrastructure.Data.Repositories;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
namespace GermanApp.Tests.Unit.Infrastructure.Data.Repositories;
[TestClass]
public class StoryRepositoryTests
{
private StorySegment CreateSegment(int id, int levelId, int? lessonId, int order)
{
var segment = StorySegment.Create(levelId, lessonId, "Content", order, "Title", "Theme");
typeof(StorySegment).GetProperty("Id")?.SetValue(segment, id);
return segment;
}
[TestMethod]
public async Task AddAsync_WithNewSegment_AddsToDbSet()
{
// Arrange
var segment = CreateSegment(0, 1, 1, 1);
var mockDbSet = new Mock<DbSet<StorySegment>>();
var options = new DbContextOptions<AppDbContext>();
var mockContext = new Mock<AppDbContext>(options);
mockDbSet.Setup(d => d.AddAsync(segment, It.IsAny<CancellationToken>()))
.Returns(ValueTask.FromResult((EntityEntry<StorySegment>?)null));
mockContext.Setup(c => c.StorySegments).Returns(mockDbSet.Object);
mockContext.Setup(c => c.SaveChangesAsync(It.IsAny<CancellationToken>()))
.ReturnsAsync(1);
var repository = new StoryRepository(mockContext.Object);
// Act
var result = await repository.AddAsync(segment);
// Assert
Assert.IsNotNull(result);
mockDbSet.Verify(d => d.AddAsync(segment, It.IsAny<CancellationToken>()), Times.Once);
mockContext.Verify(c => c.SaveChangesAsync(It.IsAny<CancellationToken>()), Times.Once);
}
[TestMethod]
public async Task UpdateAsync_WithExistingSegment_UpdatesDbSet()
{
// Arrange
var segment = CreateSegment(1, 1, 1, 1);
var mockDbSet = new Mock<DbSet<StorySegment>>();
var options = new DbContextOptions<AppDbContext>();
var mockContext = new Mock<AppDbContext>(options);
mockContext.Setup(c => c.StorySegments).Returns(mockDbSet.Object);
mockContext.Setup(c => c.SaveChangesAsync(It.IsAny<CancellationToken>()))
.ReturnsAsync(1);
var repository = new StoryRepository(mockContext.Object);
// Act
await repository.UpdateAsync(segment);
// Assert
mockDbSet.Verify(d => d.Update(segment), Times.Once);
mockContext.Verify(c => c.SaveChangesAsync(It.IsAny<CancellationToken>()), Times.Once);
}
[TestMethod]
public async Task DeleteAsync_WithExistingId_RemovesFromDbSet()
{
// Arrange
var segment = CreateSegment(1, 1, 1, 1);
var mockDbSet = new Mock<DbSet<StorySegment>>();
var options = new DbContextOptions<AppDbContext>();
var mockContext = new Mock<AppDbContext>(options);
mockDbSet.Setup(d => d.FindAsync(new object[] { 1 }, It.IsAny<CancellationToken>()))
.ReturnsAsync(segment);
mockContext.Setup(c => c.StorySegments).Returns(mockDbSet.Object);
mockContext.Setup(c => c.SaveChangesAsync(It.IsAny<CancellationToken>()))
.ReturnsAsync(1);
var repository = new StoryRepository(mockContext.Object);
// Act
await repository.DeleteAsync(1);
// Assert
mockDbSet.Verify(d => d.Remove(segment), Times.Once);
mockContext.Verify(c => c.SaveChangesAsync(It.IsAny<CancellationToken>()), Times.Once);
}
[TestMethod]
public async Task DeleteAsync_WithNonExistingId_DoesNotThrow()
{
// Arrange
var mockDbSet = new Mock<DbSet<StorySegment>>();
var options = new DbContextOptions<AppDbContext>();
var mockContext = new Mock<AppDbContext>(options);
mockDbSet.Setup(d => d.FindAsync(new object[] { 999 }, It.IsAny<CancellationToken>()))
.ReturnsAsync((StorySegment?)null);
mockContext.Setup(c => c.StorySegments).Returns(mockDbSet.Object);
mockContext.Setup(c => c.SaveChangesAsync(It.IsAny<CancellationToken>()))
.ReturnsAsync(1);
var repository = new StoryRepository(mockContext.Object);
// Act & Assert (should not throw)
await repository.DeleteAsync(999);
mockDbSet.Verify(d => d.Remove(It.IsAny<StorySegment>()), Times.Never);
}
}