EF内存数据库单元测试:Include筛选关联实体失效问题求助
解决EF Core内存数据库单元测试中Include过滤不生效的问题
问题原因
你遇到的问题是EF Core的特性导致的:当你的DbContext已经追踪了该用户的所有关联Game实体(也就是测试代码中提前添加并SaveChanges的两个Game),查询时使用Include(x => x.Games.OrderByDescending(...).Take(1))的过滤逻辑不会生效。EF Core会优先将内存中已追踪的所有关联实体填充到user.Games导航属性里,完全忽略Include里的过滤条件。
不修改业务逻辑的解决方案
方案1:创建新的DbContext实例执行被测逻辑
在测试代码中添加完测试数据并SaveChanges后,不要使用同一个上下文执行被测方法,而是创建一个全新的DbContext实例。新上下文不会追踪之前添加的实体,查询时会严格从内存数据库读取并应用Include的过滤规则,这样user.Games就只会包含权重最大的那个Game。
示例测试代码调整:
// 原测试数据添加代码 var user = fixture.Build<User>().Create(); await context.Users.AddAsync(user); foreach (var item in items) { var game = fixture.Build<Game>().With(x => x.User, user) .With(x => x.Name, item.Name).With(x => x.Weight, item.Weight).Create(); await context.Games.AddAsync(game); } await context.SaveChangesAsync(); // 创建新的上下文实例(使用相同的内存数据库配置) using var testContext = new YourDbContext(_dbContextOptions); // 将新上下文注入到被测服务中,或直接用它执行查询 var targetService = new YourBusinessService(testContext); var result = await targetService.GetUserWithTopWeightGame(userId);
方案2:Detach所有已追踪的实体
如果无法创建新的上下文,可以在保存测试数据后,将上下文追踪的所有实体都脱离追踪状态。这样上下文不再持有这些实体的引用,查询时会重新从数据库读取并应用Include的过滤条件。
示例代码:
await context.SaveChangesAsync(); // 脱离所有已追踪的实体 foreach (var entry in context.ChangeTracker.Entries()) { entry.State = EntityState.Detached; } // 继续执行被测方法逻辑 var result = await yourService.YourMethod(userId);
内容的提问来源于stack exchange,提问作者DmitryVlasov
相关产品推荐
相关产品推荐

