1

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. 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.

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();
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Paritosh
  • 4,243
  • 7
  • 47
  • 80
  • Possible duplicate of [Mocking classes that implement IQueryable with Moq](https://stackoverflow.com/questions/7048511/mocking-classes-that-implement-iqueryable-with-moq) – William Xifaras May 20 '19 at 18:08

1 Answers1

1

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). I just dumped the GetAll method into an interface called IRepository, and this is what the mock looks like. Inside of the Returns method, you have access to each of the parameters to execute or ignore as you please.

  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. Also note, of course, that I used an int for the generic parameter -- you'll replace that with whatever type you're using. It may be possible to make a mock that accepts generic parameters, but that hopefully won't be necessary!

bvoyelr
  • 920
  • 8
  • 11
  • Unfortunately, in this case Where method will no be applied when: var res = myRepo.GetAll().Where(x=>x > 2).ToList() // 1,2,3 will be returned instead of 2,3 Is there any way to apply Where to result? – Artem A Sep 16 '19 at 16:51