Search code examples
c#nunitmoq

How to Moq setup for await with ToListAsync variable which is already queried as IQurable?


Variable which is IQueryable typed list,

var requests = _genericRepository.GetIQueryable<RequestMaster>();

so for above line of code my below mock setup is worked fine

private IEnumerable<RequestMaster> FakeRequestMaster()
{
  string fakeData = @"[{
  'RequestId': '118',
  'RequestUuid':'901358ab-32e3-4a52-9182-ba68a0a03b50',
  'UserId':'klj123kj-0120-4f3c-8d29-asd213klj213lkl',
  'StatusId':'7',
  'CreatedOn':'11/28/2021 10:01:42 AM',
  'CreatedBy':'000000-0000-0000-0000-000000000000',
  'ModifiedOn':'3/23/2022 6:30:31 PM',
  'ModifiedBy':'000000-0000-0000-0000-000000000000'
  'IsActive':'true',
 }]";
 return JsonConvert.DeserializeObject<IEnumerable<RequestMaster>>(fakeData);
}

[Fact]
public async Task GetRequests_SendingValidId_ExpectedNotNull()
{
    var fakeRequestMaster = FakeRequestMaster();
    _mockGenericRepository.Setup(s => s.GetIQueryable<RequestMaster>()).Returns(fakeRequestMaster.AsQueryable);
    var result = await service.GetRequests(typeId);
    
    // Assert
    Assert.NotNull(result);
}

but after getting some data by 'await' and 'ToListAsync' then in this step test complier skipping for execute and throwing an error :

System.InvalidCastException : Unable to cast object of type 'System.Linq.EnumerableQuery 1[TMo.MWav.Data.MicrowaveModels.RequestMaster]' to type 'System.Collections.Generic.IAsyncEnumerable 1[TMo.MWav.Data.MicrowaveModels.RequestMaster]'.

So, I tried as mentioned in this link : How to mock an async repository with Entity Framework Core

var mockSetDb = new Mock<DbSet<RequestMaster>>();
mockSetDb.As<IAsyncEnumerable<RequestMaster>>().Setup(m => m.GetEnumerator()).Returns(new TestAsyncEnumerator<RequestMaster>(fakeRequestMaster.GetEnumerator()));
mockSetDb.As<IQueryable<RequestMaster>>().Setup(m => m.Provider).Returns(new TestAsyncQueryProvider<RequestMaster>(fakeRequestMaster.Provider));
mockSetDb.As<IQueryable<RequestMaster>>().Setup(m => m.Expression).Returns(fakeRequestMaster.Expression);
mockSetDb.As<IQueryable<RequestMaster>>().Setup(m => m.ElementType).Returns(fakeRequestMaster.ElementType);
mockSetDb.As<IQueryable<RequestMaster>>().Setup(m => m.GetEnumerator()).Returns(() => fakeRequestMaster.GetEnumerator());

so which is also not working, getting issues :

'IAsyncEnumerable' does not contain a definition for 'GetEnumerator' and no accessible extension method 'GetEnumerator' accepting a first argument of type 'IAsyncEnumerable' could be found (are you missing a using directive or an assembly reference?)

'IEnumerable' does not contain a definition for 'Provider' and no accessible extension method 'Provider' accepting a first argument of type 'IEnumerable' could be found (are you missing a using directive or an assembly reference?)

'IEnumerable' does not contain a definition for 'Expression' and no accessible extension method 'Expression' accepting a first argument of type 'IEnumerable' could be found (are you missing a using directive or an assembly reference?)

'IEnumerable' does not contain a definition for 'ElementType' and no accessible extension method 'ElementType' accepting a first argument of type 'IEnumerable' could be found (are you missing a using directive or an assembly reference?)

So, please can any one help me out for Moq setup for await with ToListAsync variable.


Solution

  • By install MockQueryable.Moq 5.0 package

    using MockQueryable.Moq;

    var requestMaster = RequestMaster();
    var mock = requestMaster.BuildMock();
    _mockGenericRepository.Setup(s => s.GetIQueryable<RequestMaster>()).Returns(mock);
    

    working fine.