using Health.Domain.Entities; using Health.Domain.Enums; using Health.Infrastructure.Data; using Microsoft.EntityFrameworkCore; namespace Health.Tests; /// /// 实体和数据库操作测试 /// public class EntityTests { private AppDbContext CreateDbContext() { var options = new DbContextOptionsBuilder() .UseInMemoryDatabase(Guid.NewGuid().ToString()) .Options; return new AppDbContext(options); } [Fact] public async Task Create_HealthRecord_Should_Persist() { using var db = CreateDbContext(); var user = new User { Id = Guid.NewGuid(), Phone = "13800138000", CreatedAt = DateTime.UtcNow, UpdatedAt = DateTime.UtcNow }; db.Users.Add(user); await db.SaveChangesAsync(); var record = new HealthRecord { Id = Guid.NewGuid(), UserId = user.Id, MetricType = HealthMetricType.BloodPressure, Systolic = 128, Diastolic = 82, Unit = "mmHg", Source = HealthRecordSource.AiEntry, RecordedAt = DateTime.UtcNow, IsAbnormal = false, }; db.HealthRecords.Add(record); await db.SaveChangesAsync(); var saved = await db.HealthRecords.FirstOrDefaultAsync(r => r.UserId == user.Id); Assert.NotNull(saved); Assert.Equal(128, saved!.Systolic); Assert.Equal(82, saved.Diastolic); Assert.Equal(HealthMetricType.BloodPressure, saved.MetricType); } [Fact] public async Task Abnormal_BloodPressure_Should_Flag_IsAbnormal() { var record = new HealthRecord { Systolic = 155, Diastolic = 95, MetricType = HealthMetricType.BloodPressure, }; var isAbnormal = record.Systolic >= 140 || record.Diastolic >= 90 || record.Systolic <= 89 || record.Diastolic <= 59; Assert.True(isAbnormal); } [Fact] public async Task Normal_BloodPressure_Should_Not_Flag() { var record = new HealthRecord { Systolic = 128, Diastolic = 82, MetricType = HealthMetricType.BloodPressure, }; var isAbnormal = record.Systolic >= 140 || record.Diastolic >= 90 || record.Systolic <= 89 || record.Diastolic <= 59; Assert.False(isAbnormal); } [Fact] public async Task Create_Medication_Should_Persist_With_TimeOfDay() { using var db = CreateDbContext(); var user = new User { Id = Guid.NewGuid(), Phone = "13800138000", CreatedAt = DateTime.UtcNow, UpdatedAt = DateTime.UtcNow }; db.Users.Add(user); await db.SaveChangesAsync(); var med = new Medication { Id = Guid.NewGuid(), UserId = user.Id, Name = "阿司匹林", Dosage = "100mg", Frequency = MedicationFrequency.Daily, TimeOfDay = [new TimeOnly(8, 0)], Source = MedicationSource.AiEntry, IsActive = true, }; db.Medications.Add(med); await db.SaveChangesAsync(); var saved = await db.Medications.FirstOrDefaultAsync(m => m.UserId == user.Id); Assert.NotNull(saved); Assert.Equal("阿司匹林", saved!.Name); Assert.Equal("100mg", saved.Dosage); Assert.Single(saved.TimeOfDay); Assert.Equal(8, saved.TimeOfDay[0].Hour); } [Fact] public async Task Medication_Confirm_Should_Create_Log() { using var db = CreateDbContext(); var user = new User { Id = Guid.NewGuid(), Phone = "13800138000", CreatedAt = DateTime.UtcNow, UpdatedAt = DateTime.UtcNow }; db.Users.Add(user); var med = new Medication { Id = Guid.NewGuid(), UserId = user.Id, Name = "阿托伐他汀", Dosage = "20mg", Frequency = MedicationFrequency.Daily, Source = MedicationSource.Prescription, IsActive = true }; db.Medications.Add(med); await db.SaveChangesAsync(); // 打卡 var log = new MedicationLog { Id = Guid.NewGuid(), MedicationId = med.Id, UserId = user.Id, Status = MedicationLogStatus.Taken, ScheduledTime = new TimeOnly(20, 0), ConfirmedAt = DateTime.UtcNow, }; db.MedicationLogs.Add(log); await db.SaveChangesAsync(); var saved = await db.MedicationLogs.FirstOrDefaultAsync(l => l.MedicationId == med.Id); Assert.NotNull(saved); Assert.Equal(MedicationLogStatus.Taken, saved!.Status); } [Fact] public async Task Conversation_With_Messages_Should_Work() { using var db = CreateDbContext(); var user = new User { Id = Guid.NewGuid(), Phone = "13800138000", CreatedAt = DateTime.UtcNow, UpdatedAt = DateTime.UtcNow }; db.Users.Add(user); await db.SaveChangesAsync(); var conv = new Conversation { Id = Guid.NewGuid(), UserId = user.Id, AgentType = AgentType.Default, Title = "血压咨询", CreatedAt = DateTime.UtcNow, UpdatedAt = DateTime.UtcNow }; db.Conversations.Add(conv); var msg1 = new ConversationMessage { Id = Guid.NewGuid(), ConversationId = conv.Id, Role = MessageRole.User, Content = "血压 135/85", CreatedAt = DateTime.UtcNow }; var msg2 = new ConversationMessage { Id = Guid.NewGuid(), ConversationId = conv.Id, Role = MessageRole.Assistant, Content = "收到!已记录", CreatedAt = DateTime.UtcNow }; db.ConversationMessages.AddRange(msg1, msg2); conv.MessageCount = 2; await db.SaveChangesAsync(); var messages = await db.ConversationMessages.Where(m => m.ConversationId == conv.Id).OrderBy(m => m.CreatedAt).ToListAsync(); Assert.Equal(2, messages.Count); Assert.Equal("血压 135/85", messages[0].Content); Assert.Equal("收到!已记录", messages[1].Content); } [Fact] public async Task DietRecord_With_FoodItems_Should_Work() { using var db = CreateDbContext(); var user = new User { Id = Guid.NewGuid(), Phone = "13800138000", CreatedAt = DateTime.UtcNow, UpdatedAt = DateTime.UtcNow }; db.Users.Add(user); await db.SaveChangesAsync(); var diet = new DietRecord { Id = Guid.NewGuid(), UserId = user.Id, MealType = MealType.Lunch, TotalCalories = 644, HealthScore = 3, RecordedAt = DateOnly.FromDateTime(DateTime.Now), }; diet.FoodItems.Add(new DietFoodItem { Id = Guid.NewGuid(), Name = "米饭", Portion = "1碗", Calories = 174, SortOrder = 1 }); diet.FoodItems.Add(new DietFoodItem { Id = Guid.NewGuid(), Name = "红烧肉", Portion = "5块", Calories = 470, Warning = "脂肪偏高", SortOrder = 2 }); db.DietRecords.Add(diet); await db.SaveChangesAsync(); var saved = await db.DietRecords.Include(d => d.FoodItems).FirstOrDefaultAsync(d => d.UserId == user.Id); Assert.NotNull(saved); Assert.Equal(2, saved!.FoodItems.Count); Assert.Equal(644, saved.TotalCalories); } [Fact] public async Task HealthArchive_Should_Store_All_Fields() { using var db = CreateDbContext(); var user = new User { Id = Guid.NewGuid(), Phone = "13800138000", CreatedAt = DateTime.UtcNow, UpdatedAt = DateTime.UtcNow }; db.Users.Add(user); await db.SaveChangesAsync(); var archive = new HealthArchive { Id = Guid.NewGuid(), UserId = user.Id, Diagnosis = "冠心病", SurgeryType = "PCI支架植入术", SurgeryDate = new DateOnly(2026, 3, 15), Allergies = ["青霉素"], DietRestrictions = ["低盐", "低脂"], ChronicDiseases = ["高血压", "高血脂"], FamilyHistory = "父亲冠心病", }; db.HealthArchives.Add(archive); await db.SaveChangesAsync(); var saved = await db.HealthArchives.FirstOrDefaultAsync(a => a.UserId == user.Id); Assert.NotNull(saved); Assert.Equal("冠心病", saved!.Diagnosis); Assert.Equal(2, saved.DietRestrictions.Count); Assert.Contains("低盐", saved.DietRestrictions); } [Fact] public async Task ExercisePlan_Weekly_Tracking_Should_Work() { using var db = CreateDbContext(); var user = new User { Id = Guid.NewGuid(), Phone = "13800138000", CreatedAt = DateTime.UtcNow, UpdatedAt = DateTime.UtcNow }; db.Users.Add(user); await db.SaveChangesAsync(); var monday = new DateOnly(2026, 6, 1); var plan = new ExercisePlan { Id = Guid.NewGuid(), UserId = user.Id, WeekStartDate = monday }; plan.Items.Add(new ExercisePlanItem { Id = Guid.NewGuid(), DayOfWeek = 0, ExerciseType = "散步", DurationMinutes = 30, IsCompleted = true, CompletedAt = DateTime.UtcNow }); plan.Items.Add(new ExercisePlanItem { Id = Guid.NewGuid(), DayOfWeek = 1, ExerciseType = "慢跑", DurationMinutes = 20 }); plan.Items.Add(new ExercisePlanItem { Id = Guid.NewGuid(), DayOfWeek = 2, IsRestDay = true }); db.ExercisePlans.Add(plan); await db.SaveChangesAsync(); var saved = await db.ExercisePlans.Include(p => p.Items).FirstOrDefaultAsync(p => p.UserId == user.Id); Assert.NotNull(saved); Assert.Equal(3, saved!.Items.Count); var completed = saved.Items.Count(i => i.IsCompleted); Assert.Equal(1, completed); } }