You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 15:45:30