使用 moq 模拟对 IQueryable 的调用

问题描述 投票:0回答:1

我正在尝试最小起订量我拥有的存储库,其定义为:

public IQueryable<TEntity> GetAll(
    Expression<Func<TEntity, bool>> predicate = null,
    Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
    Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> include = null,
    bool disableTracking = true
)

有办法嘲笑这个吗?我希望使用我提供存储库的模拟数据来执行查询。我不知道如何告诉 MOQ,当我调用 GetAll 时,我希望它仍然运行传入的查询,但针对我提供的数据集执行此操作。所以它不会进入数据库,而是针对我配置的模拟集。我能够创建数据,它包含 12 条记录,但我希望 getall moq 调用来执行其查询并将其过滤为仅应返回的 2 条记录。

调用发生的实际服务是:

var list = await _unitOfWork.GetRepository<CASE_ACTIVITY>()
    .GetAll(predicate: x => 
        x.SM_SITE_ID == siteId && 
        x.CMS_USER_ID == userId && 
        x.IS_DELETED == "N" &&
        x.Appointment.IS_DELETED == "N" &&
        x.Appointment.IS_ARCHIVED == "N" &&
        x.IS_ARCHIVED == "N" &&
        (
            (x.Appointment.APPOINTMENT_DATETIME.HasValue &&
             x.Appointment.APPOINTMENT_DATETIME.Value.Date == DateTime.Today.Date) ||
            (!x.Appointment.APPOINTMENT_DATETIME.HasValue &&
            x.ACTIVITY_STATUS_ID == _appSettings.CASE_ACTIVITY_STATUS_ID_PENDING)
        )
    )
    .Include(x => x.Activity_Lookup)
    .Include(x => x.Appointment)
    .ThenInclude(x => x.Cms_Client)
    .Include(x => x.Cms_Case)
    .ToListAsync();
c# unit-testing moq
1个回答
1
投票

假设您对

GetRepository()
方法有足够的控制权以使 it 返回您的模拟存储库,则模拟方法本身相当简单(如果有点冗长)。我刚刚将
GetAll
方法转储到名为
IRepository
的接口中,这就是模拟的样子。在
Returns
方法内部,您可以根据需要访问要执行或忽略的每个参数。

  var mock = new Moq.Mock<IRepository>();
  mock.Setup(a => a.GetAll<int>(It.IsAny<Expression<Func<int, bool>>>(), It.IsAny<Func<IQueryable<int>, IOrderedQueryable<int>>>(), It.IsAny<Func<IQueryable<int>, IIncludableQueryable<int, object>>>(), It.IsAny<bool>()))
    .Returns<Expression<Func<int, bool>>, Func<IQueryable<int>, IOrderedQueryable<int>>, Func<IQueryable<int>, IIncludableQueryable<int, object>>, bool>((param1, param2, param3, param4) =>
    {
      return new[] { 1, 2, 3 }.AsQueryable();
    });

  var result = mock.Object.GetAll<int>();

从这里开始,如果不看到更多代码,我们就无能为力。不过,从抽象的角度来说,您将把您的

mock.Object
(其类型为
IRepository
)并将其提供给 GetRepository() 从中提取的任何集合。当然,还要注意,我使用 int 作为通用参数——您可以将其替换为您使用的任何类型。也许可以制作一个接受通用参数的模拟,但希望这不是必需的!

© www.soinside.com 2019 - 2024. All rights reserved.