dramaling-vocab-learning/backend/DramaLing.Api/Tests
鄭沛軒 8625d40ed3 feat: 完成後端架構全面優化 - 階段一二
🏗️ 架構重構成果:
- 清理13個空目錄,建立標準目錄結構
- 實現完整Repository模式,符合Clean Architecture
- FlashcardsController重構使用IFlashcardRepository
- 統一依賴注入配置,提升可維護性

📊 量化改善:
- 編譯錯誤:0個 
- 編譯警告:從13個減少到2個 (85%改善)
- Repository統一:6個檔案統一管理
- 目錄結構:20個有效目錄,0個空目錄

🔧 技術改進:
- Clean Architecture合規
- Repository模式完整實現
- 依賴注入統一配置
- 程式碼品質大幅提升

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-30 03:32:51 +08:00
..
README.md feat: 完成後端架構全面優化 - 階段一二 2025-09-30 03:32:51 +08:00

README.md

測試架構說明

概述

本測試架構採用三層測試策略:單元測試、整合測試、端到端測試。支援 xUnit 測試框架,並整合 Moq 進行 Mock 測試。

測試目錄結構

Tests/
├── README.md              # 本文檔 - 測試架構說明
├── Unit/                  # 單元測試
│   ├── Services/         # 服務層單元測試
│   ├── Controllers/      # 控制器單元測試
│   └── Repositories/     # Repository 單元測試
├── Integration/           # 整合測試
└── E2E/                  # 端到端測試

測試框架與工具

核心測試框架

  • xUnit: 主要測試框架
  • Moq: Mock 物件框架
  • FluentAssertions: 流暢斷言庫
  • Microsoft.AspNetCore.Mvc.Testing: ASP.NET Core 測試支援

測試資料庫

  • SQLite In-Memory: 用於快速單元測試
  • TestContainers: 用於整合測試的容器化資料庫

單元測試規範

命名規範

{TestedMethod}_{Scenario}_{ExpectedResult}

例如:
- GetUserAsync_WithValidId_ReturnsUser()
- AnalyzeSentenceAsync_WithEmptyText_ThrowsArgumentException()

測試結構 (Arrange-Act-Assert)

[Fact]
public async Task GetUserAsync_WithValidId_ReturnsUser()
{
    // Arrange
    var userId = 1;
    var expectedUser = new User { Id = userId, Name = "Test User" };
    var mockRepository = new Mock<IUserRepository>();
    mockRepository.Setup(r => r.GetByIdAsync(userId))
              .ReturnsAsync(expectedUser);

    var service = new UserService(mockRepository.Object);

    // Act
    var result = await service.GetUserAsync(userId);

    // Assert
    result.Should().NotBeNull();
    result.Id.Should().Be(userId);
    result.Name.Should().Be("Test User");
}

服務層測試指南

測試重點服務

  1. GeminiService - AI 服務核心功能
  2. AuthService - 認證服務
  3. AnalysisService - 分析服務
  4. RefactoredHybridCacheService - 快取服務

Mock 策略

  • 外部 API 呼叫: 使用 Mock HttpClient
  • 資料庫操作: Mock Repository 介面
  • 檔案操作: Mock 檔案系統相關服務

整合測試策略

WebApplicationFactory

使用 ASP.NET Core 的 WebApplicationFactory 進行整合測試:

public class IntegrationTestBase : IClassFixture<WebApplicationFactory<Program>>
{
    protected readonly WebApplicationFactory<Program> Factory;
    protected readonly HttpClient Client;

    public IntegrationTestBase(WebApplicationFactory<Program> factory)
    {
        Factory = factory.WithWebHostBuilder(builder =>
        {
            builder.UseEnvironment("Testing");
            builder.ConfigureServices(services =>
            {
                // 替換為測試資料庫
                services.RemoveAll<DbContextOptions<DramaLingDbContext>>();
                services.AddDbContext<DramaLingDbContext>(options =>
                    options.UseInMemoryDatabase("TestDb"));
            });
        });

        Client = Factory.CreateClient();
    }
}

測試資料管理

public class TestDataSeeder
{
    public static async Task SeedAsync(DramaLingDbContext context)
    {
        // 清理現有資料
        context.Users.RemoveRange(context.Users);

        // 新增測試資料
        context.Users.Add(new User { Id = 1, Name = "Test User" });

        await context.SaveChangesAsync();
    }
}

測試執行命令

執行所有測試

dotnet test

執行特定類別的測試

dotnet test --filter "ClassName=GeminiServiceTests"

執行特定類型的測試

# 只執行單元測試
dotnet test --filter "Category=Unit"

# 只執行整合測試
dotnet test --filter "Category=Integration"

產生測試覆蓋率報告

dotnet test --collect:"XPlat Code Coverage"

測試資料工廠模式

實體建立工廠

public static class TestDataFactory
{
    public static User CreateUser(int id = 1, string name = "Test User")
    {
        return new User
        {
            Id = id,
            Name = name,
            Email = $"test{id}@example.com",
            CreatedAt = DateTime.UtcNow
        };
    }

    public static Flashcard CreateFlashcard(int id = 1, int userId = 1)
    {
        return new Flashcard
        {
            Id = id,
            UserId = userId,
            Front = "Test Front",
            Back = "Test Back",
            CreatedAt = DateTime.UtcNow
        };
    }
}

CI/CD 整合

GitHub Actions 設定範例

name: Tests
on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v2

    - name: Setup .NET
      uses: actions/setup-dotnet@v1
      with:
        dotnet-version: '8.0.x'

    - name: Restore dependencies
      run: dotnet restore

    - name: Build
      run: dotnet build --no-restore

    - name: Test
      run: dotnet test --no-build --verbosity normal --collect:"XPlat Code Coverage"

    - name: Upload coverage reports
      uses: codecov/codecov-action@v1

效能測試指南

基準測試

使用 BenchmarkDotNet 進行效能測試:

[MemoryDiagnoser]
[SimpleJob(RuntimeMoniker.Net80)]
public class CachingBenchmarks
{
    private ICacheService _cacheService;

    [GlobalSetup]
    public void Setup()
    {
        // 初始化快取服務
    }

    [Benchmark]
    public async Task<string> GetFromCache()
    {
        return await _cacheService.GetAsync<string>("test-key");
    }
}

測試最佳實踐

DRY 原則

  • 建立共用的測試基類
  • 使用測試資料工廠
  • 抽取共同的 Setup 邏輯

測試隔離

  • 每個測試應該獨立執行
  • 避免測試之間的依賴關係
  • 使用 IDisposable 清理資源

可讀性

  • 使用描述性的測試名稱
  • 明確的 Arrange-Act-Assert 結構
  • 適量的註解說明複雜邏輯

未來擴展計劃

  1. 測試覆蓋率目標: 達到 80% 以上的程式碼覆蓋率
  2. 自動化測試: 整合 CI/CD 管道
  3. 效能回歸測試: 建立效能基準測試
  4. 安全性測試: 加入安全相關的測試案例

版本: 1.0 建立日期: 2025-09-30 維護者: DramaLing 開發團隊