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
相关产品推荐
相关产品推荐

