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

EF Core 8中Mock AddAsync方法如何正确返回EntityEntry?

问题:EF Core AddAsync Mock返回null导致测试失败

待测试方法

public async Task<ISnapshot> CloneSnapshot(int snapshotIdToClone, string newName)
{
    var snapshotToClone = _databaseContext.Snapshots.Include(s => s.Entries).FirstOrDefault(s => s.Id == snapshotIdToClone);
    var clonedSnapshot = snapshotToClone.Clone() as Snapshot;
    clonedSnapshot.Name = newName;
    clonedSnapshot.Id = 0;
    clonedSnapshot.IsActive = false;
    clonedSnapshot.ActivationDate = null;

    var newSnapshot = await _databaseContext.Set<Snapshot>().AddAsync(clonedSnapshot);   
    await _databaseContext.SaveChangesAsync();

    return newSnapshot.Entity;
} 

现有Mock代码

private static ConfigurationProvider CreateConfigurationProvider(List<Snapshot> snapshots)
{
    var mockDbContext = new Mock<DatabaseContext>(new DbContextOptions<DatabaseContext>());
    mockDbContext.Setup(c => c.Snapshots).Returns(CreateDbSetMock(snapshots.AsQueryable()).Object);
    var snapshotMock = CreateDbSetMock(snapshots.AsQueryable());
    snapshotMock.Setup(_ => _.AddAsync(It.IsAny<Snapshot>(), It.IsAny<System.Threading.CancellationToken>()))
        .Callback((Snapshot model, CancellationToken token) => { snapshots.Add(model); })
        .Returns((Snapshot model, CancellationToken token) => ValueTask.FromResult((EntityEntry<Snapshot>)null));
    mockDbContext.Setup(x => x.Set<Snapshot>()).Returns(snapshotMock.Object);
    mockDbContext.Setup(_ => _.SaveChangesAsync(It.IsAny<CancellationToken>())).Returns(() => Task.FromResult(1));

    var provider = new ConfigurationProvider(mockDbContext.Object);
    return provider;
}

解决方案

问题出在AddAsync的Returns语句返回了null的EntityEntry<Snapshot>,导致newSnapshot.Entity无法获取有效实体。只需修改Returns部分,返回一个包含传入模型的模拟EntityEntry实例即可:

snapshotMock.Setup(_ => _.AddAsync(It.IsAny<Snapshot>(), It.IsAny<System.Threading.CancellationToken>()))
    .Callback((Snapshot model, CancellationToken token) => { snapshots.Add(model); })
    .Returns((Snapshot model, CancellationToken token) => 
    {
        // 模拟EntityEntry,让其Entity属性指向传入的模型
        var entryMock = new Mock<EntityEntry<Snapshot>>();
        entryMock.Setup(e => e.Entity).Returns(model);
        return ValueTask.FromResult(entryMock.Object);
    });

这样修改后,AddAsync返回的EntityEntry实例的Entity属性会正确指向克隆后的Snapshot对象,方法里的newSnapshot.Entity就能拿到有效实体,测试即可正常运行。

内容的提问来源于stack exchange,提问作者krul

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 23:12:14