仅允许非 Development 环境运行。 只允许写入没有业务数据的独立空库。 演示数据使用单个 InnoDB 事务,失败整体回滚;迁移 DDL 仍单独执行,因为 MySQL 8.4 的 DDL 会隐式提交。MySQL 事务文档、隐式提交说明 不包含通用测试密码或学生、教师登录账号。 包含校区、学期、30 间教室、16 个学院、52 个专业、104 个班级、128 名教师、3,640 名学生和148门课程。
124 lines
4.6 KiB
C#
124 lines
4.6 KiB
C#
using Jiaowu.Api.Domain.Academic;
|
|
using Jiaowu.Api.Infrastructure.Persistence;
|
|
using Microsoft.Data.Sqlite;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using Microsoft.Extensions.Logging.Abstractions;
|
|
|
|
namespace Jiaowu.Api.Tests;
|
|
|
|
public sealed class DemoDataSeederTests
|
|
{
|
|
[Fact]
|
|
public async Task SeedAsync_populates_an_empty_business_database()
|
|
{
|
|
await using var connection = new SqliteConnection("Data Source=:memory:");
|
|
await connection.OpenAsync();
|
|
await using var db = await CreateDatabaseAsync(connection);
|
|
await SeedCourseCategoriesAsync(db);
|
|
|
|
var seeder = new DemoDataSeeder(
|
|
db,
|
|
NullLogger<DemoDataSeeder>.Instance);
|
|
|
|
await seeder.SeedAsync();
|
|
|
|
Assert.Equal(1, await db.Campuses.CountAsync());
|
|
Assert.Equal(16, await db.Colleges.CountAsync());
|
|
Assert.Equal(52, await db.Majors.CountAsync());
|
|
Assert.Equal(104, await db.AdministrativeClasses.CountAsync());
|
|
Assert.Equal(128, await db.Teachers.CountAsync());
|
|
Assert.Equal(3640, await db.Students.CountAsync());
|
|
Assert.Equal(148, await db.Courses.CountAsync());
|
|
Assert.Equal(736, await db.TeacherCourseApplications.CountAsync());
|
|
Assert.Equal(1, await db.AcademicTerms.CountAsync(x => x.IsCurrent));
|
|
Assert.Equal(30, await db.Classrooms.CountAsync());
|
|
}
|
|
|
|
[Fact]
|
|
public async Task SeedAsync_rejects_a_database_with_business_data()
|
|
{
|
|
await using var connection = new SqliteConnection("Data Source=:memory:");
|
|
await connection.OpenAsync();
|
|
await using var db = await CreateDatabaseAsync(connection);
|
|
await SeedCourseCategoriesAsync(db);
|
|
db.Campuses.Add(new Campus { Code = "EXISTING", Name = "现有校区" });
|
|
await db.SaveChangesAsync();
|
|
|
|
var seeder = new DemoDataSeeder(
|
|
db,
|
|
NullLogger<DemoDataSeeder>.Instance);
|
|
|
|
var exception = await Assert.ThrowsAsync<InvalidOperationException>(
|
|
() => seeder.SeedAsync());
|
|
|
|
Assert.Contains("只允许写入没有业务数据的新数据库", exception.Message);
|
|
Assert.Contains("校区", exception.Message);
|
|
Assert.Equal(1, await db.Campuses.CountAsync());
|
|
}
|
|
|
|
[Fact]
|
|
public async Task SeedAsync_rolls_back_all_demo_rows_when_insertion_fails()
|
|
{
|
|
await using var connection = new SqliteConnection("Data Source=:memory:");
|
|
await connection.OpenAsync();
|
|
await using var db = await CreateDatabaseAsync(connection);
|
|
await SeedCourseCategoriesAsync(db);
|
|
var practiceCategory = await db.CourseCategories
|
|
.SingleAsync(x => x.Code == "PRACTICE");
|
|
db.CourseCategories.Remove(practiceCategory);
|
|
await db.SaveChangesAsync();
|
|
|
|
var seeder = new DemoDataSeeder(
|
|
db,
|
|
NullLogger<DemoDataSeeder>.Instance);
|
|
|
|
await Assert.ThrowsAsync<KeyNotFoundException>(() => seeder.SeedAsync());
|
|
|
|
db.ChangeTracker.Clear();
|
|
Assert.Equal(0, await db.Campuses.CountAsync());
|
|
Assert.Equal(0, await db.Colleges.CountAsync());
|
|
Assert.Equal(0, await db.Students.CountAsync());
|
|
Assert.Equal(0, await db.Courses.CountAsync());
|
|
Assert.Equal(0, await db.AcademicTerms.CountAsync());
|
|
Assert.Equal(0, await db.Classrooms.CountAsync());
|
|
}
|
|
|
|
private static async Task<AppDbContext> CreateDatabaseAsync(
|
|
SqliteConnection connection)
|
|
{
|
|
var options = new DbContextOptionsBuilder<AppDbContext>()
|
|
.UseSqlite(connection)
|
|
.Options;
|
|
var db = new AppDbContext(options);
|
|
await db.Database.EnsureCreatedAsync();
|
|
return db;
|
|
}
|
|
|
|
private static async Task SeedCourseCategoriesAsync(AppDbContext db)
|
|
{
|
|
db.CourseCategories.AddRange(
|
|
CreateCategory("BASIC", "基础课程", 10),
|
|
CreateCategory("MORAL", "德育课程", 20),
|
|
CreateCategory("AESTHETIC", "美育课程", 30),
|
|
CreateCategory("LABOR", "劳动教育", 40),
|
|
CreateCategory("INNOVATION", "创新创业", 50),
|
|
CreateCategory("ENGLISH", "大学英语", 60),
|
|
CreateCategory("SPORTS", "大学体育", 70),
|
|
CreateCategory("MILITARY", "国防教育", 80),
|
|
CreateCategory("MAJOR", "专业教育", 90),
|
|
CreateCategory("PRACTICE", "实践教学", 100));
|
|
await db.SaveChangesAsync();
|
|
}
|
|
|
|
private static CourseCategory CreateCategory(
|
|
string code,
|
|
string name,
|
|
int sortOrder) =>
|
|
new()
|
|
{
|
|
Code = code,
|
|
Name = name,
|
|
SortOrder = sortOrder
|
|
};
|
|
}
|