简体   繁体   English

使用moq模拟对IQueryable的呼叫

[英]Mock a call to IQueryable using moq

I'm trying to moq a repository I have which is defined as: 我正在尝试收集一个我定义的存储库:

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)

Is there a way to mock this? 有没有办法模拟这个? I want the query to execute, using the mock data i supply the repos. 我想使用我提供的回购数据来执行查询。 I'm not sure how to tell MOQ that when I call GetAll I want it to still run the query that is passed in, but do it aganist the dataset I supply. 我不确定如何告诉MOQ,当我调用GetAll时,我希望它仍然运行传入的查询,但是这样做可以消除我提供的数据集。 so it's not going to the db but against the mock set which I've configured. 因此它不会进入数据库,而是针对我配置的模拟集。 I'm able to create the data, it contain 12 records, but I want the getall moq call to execute it's query and filter it to just the 2 that should be returned. 我能够创建数据,它包含12条记录,但是我希望getall moq调用执行它的查询并将其过滤为仅应返回的2条记录。

The actual service where the call happens is: 发生呼叫的实际服务是:

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();

Assuming you have enough control over the GetRepository() method to make it return your mock repository, mocking the method itself is fairly straightforward (if a little verbose). 假设你有足够的控制权GetRepository()方法, 使其返回你的模拟库,嘲讽的方法本身是相当简单的(如果有点冗长)。 I just dumped the GetAll method into an interface called IRepository , and this is what the mock looks like. 我只是将GetAll方法转储到名为IRepository的接口中,这就是模拟的样子。 Inside of the Returns method, you have access to each of the parameters to execute or ignore as you please. 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>();

From here, we can't help much without seeing more code. 从这里开始,如果看不到更多代码,我们将无济于事。 In abstract terms, though, you'll take your mock.Object (which is of type IRepository ) and feed it to whatever collection GetRepository() draws from. 但是,用抽象的术语来说,您将使用您的mock.Object (类型为IRepository )并将其提供给从中获取GetRepository()的任何集合。 Also note, of course, that I used an int for the generic parameter -- you'll replace that with whatever type you're using. 当然,还请注意,我对通用参数使用了int -您将使用任何类型将其替换。 It may be possible to make a mock that accepts generic parameters, but that hopefully won't be necessary! 可以制作一个接受通用参数的模拟程序,但希望没有必要!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM