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

使用Moq测试含EF Shadow Property的查询方法的方案咨询

问题1:是否可以Mock Shadow Property?具体如何实现?

可以实现,但不建议用Moq直接Mock GetAll 方法的返回集合,原因是:
EF.Property 是EF Core专属的查询方法,只有EF Core的查询提供者(比如数据库查询提供者、内存数据库提供者)能正确解析这个方法。如果你直接Mock返回内存List<AppUser>,执行LINQ to Objects的时候会因为实体类没有定义Action属性直接抛出运行时异常。

推荐最优实现方案:用EF Core官方提供的内存数据库做测试,完全不需要Mock DbContext,步骤如下:

  1. 安装Nuget包 Microsoft.EntityFrameworkCore.InMemory
  2. 单元测试初始化阶段,创建使用内存数据库的DbContext实例,确保你的DbContext配置中已经为AppUser定义了Action Shadow Property
  3. 构造测试用的AppUser数据,通过DbContext的Entry API给Shadow Property赋值:
var testUser = new AppUser { Id = 1, CreatedBy = 2 /* 其他属性赋值 */ };
dbContext.Add(testUser);
// 给Shadow Property赋值
dbContext.Entry(testUser).Property("Action").CurrentValue = "DELETE";
await dbContext.SaveChangesAsync();
  1. 直接将这个DbContext实例注入到你的业务类中,调用GetUsersByCreator方法即可正常执行包含EF.Property的查询逻辑,覆盖所有测试场景。

如果一定要用Moq做Mock,需要对查询逻辑做抽象改造:
你可以将包含Shadow Property判断的逻辑提取为可注入的接口方法,比如:

public interface IAppUserQueryFilter
{
    bool IsDeleted(AppUser user);
}
// 生产环境实现
public class EfAppUserQueryFilter : IAppUserQueryFilter
{
    public bool IsDeleted(AppUser user) => EF.Property<string>(user, "Action") == "DELETE";
}

单元测试时直接Mock IAppUserQueryFilter的IsDeleted方法返回你需要的布尔值即可,不过这种方案需要修改生产代码,性价比低于内存数据库方案。


问题2:是否应当直接将Action字段添加到实体模型中?

如果你确认Action是纯技术字段,仅用于数据库层的存储过程同步逻辑,业务层全程不需要感知这个字段的存在,就不需要添加到实体模型中,保持Shadow Property的设置完全合理,避免无关的技术字段污染业务实体的定义。
只有当后续有较多业务逻辑需要直接读写这个字段时,再考虑将其加入实体模型即可。

小提示:你提供的建表SQL存在两处问题:

  1. Name VARCHAR(MAX) NO NULL 应为 Name VARCHAR(MAX) NOT NULL
  2. 两个外键配置错误,当前是将主键Id引用自身Id,如果要实现CreatedBy、UpdatedBy关联创建人、修改人,应该改为:
CONSTRAINT FK_APPUSER_CREATION FOREIGN KEY (CreatedBy) REFERENCES AppUser (Id),
CONSTRAINT FK_APPUSER_MODIFICATION FOREIGN KEY (UpdatedBy) REFERENCES AppUser (Id)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 19:54:04