Home > other >  System.Exception : The provider for the source 'IQueryable' doesn't implement 'I
System.Exception : The provider for the source 'IQueryable' doesn't implement 'I

Time:12-23

I am working with xunit and moq.

I am trying to test FindAsyncTestAsync method return something (not null) using xUnit and Moq.

I have instantiated all the required mock repository instances using constructor. I have also instantiated the ParticipantService in the test method.

[Fact]
public async Task FindAsyncTestAsync()
{
    var participantList = ParticipantMockData.ListAllAsyncEntity(); // not null. length is 2

   _participantRepository.Setup(_ => _.FindAsync(new Guid("ffbf486f-bf31-4bb4-8fc2-5beaae59e127")))
         .Returns(Task.FromResult(participantList[0]));   // soemthing is wrong here. I don't know

   var sut = new ParticipantService(
     _participantRepository.Object,
     _participantSupportNeed.Object,
     _participantConnection.Object,
     _participantDisability.Object,
     _participantMedicalCondition.Object,
     _supportNeed.Object,
     _disabilityn.Object,
     _medicalCodition.Object,
     _participantApplicationUser.Object,
     _appLogger.Object);

   var result = await sut.FindAsync(new Guid("ffbf486f-bf31-4bb4-8fc2-5beaae59e127"));

   Assert.NotNull(result);

   Assert.Equal(participantList[0].Id, result?.Id);
 }

Test respond is:

 Message: 
    System.Exception : The provider for the source 'IQueryable' doesn't implement 'IAsyncQueryProvider'. Only providers that implement 'IAsyncQueryProvider' can be used for Entity Framework asynchronous operations.

IRepository.cs

public interface IRepository<E> where E : IEntityBase
{
    Task<List<E>> ListAsync(bool withInactives = false);
    IQueryable<E> AsNoTracking(bool withInactives = false);
    Task<E?> FindAsync(params object[] keyValues);
}

FindAsync method in ParticipantService

   public async Task<ParticipantAsyncModel?> FindAsync(Guid id)
    {
        try
        {
            var participant = await participantRepository.AsNoTracking()
            .Where(a => a.Id == id)
            .Include(a => a.ParticipantAddresses)
            .Include(a => a.ParticipantConnections)!.ThenInclude(a => a.Connection)
            .Include(a => a.ParticipantApplicationUsers)!.ThenInclude(a => a.ApplicationUser)
            .FirstOrDefaultAsync();

            var participantView =
                 new ParticipantAsyncModel()
                 {
                    // object removed for simplistic 
                 };

            if (participantView is null) return null;

            var participantModel = participantView.Adapt<ParticipantAsyncModel>();
            return participantModel;
        }
        catch (Exception ex)
        {
            throw new Exception(ex.Message);
        }

    }

Can anyone help me to find the problem.

CodePudding user response:

// soemthing is wrong here. I don't know

Nothing is with the setup per ce, it will work for IRepository.FindAsync call just fine, the problem here is that you are not invoking this method in ParticipantService.FindAsync, you are invoking IRepository.AsNoTracking which obviously was not setup correctly. As a quick fix you can use EF Core in-memory database to return from IRepository.AsNoTracking mock, but I would say you should reconsider the whole solution design.

There are quite a lot of developers which consider using (generic) repository over EF as antipattern (for example cause EF is already implementing repository pattern, as well as Unit Of Work), but even if you are not ready to make such drastic design changes, you should consider scrapping method returning IQueryable from the repository due to the "leaky abstraction" created here - clients (like ParticipantService in FindAsync) rely on the IQueryable returned from the method to be EF Core IQueryable (or something which supports all EF Core extension methods like AsNoTracking, Include, etc., see EntityFrameworkQueryableExtensions), which is why you have the exception in question.

CodePudding user response:

Mocking AsNoTracking is working for me.


            //1 - create a List<T> with test items
            var participantList = ParticipantMockData.ListAllAsyncEntity();

            //2 - build mock by extension
            var mock = participantList.AsQueryable().BuildMock();

            //3 - setup the mock as Queryable for Moq
            _participantRepository.Setup(x => x.AsNoTracking(false)).Returns(mock);


            var sut = new ParticipantService(
            _participantRepository.Object, _participantSupportNeed.Object, _participantConnection.Object, _participantDisability.Object, _participantMedicalCondition.Object, _supportNeed.Object, _disability.Object, _medicalCondition.Object, _participantApplicationUser.Object, _appLogger.Object);

            var result = await sut.FindAsync(new Guid("ffbf486f-bf31-4bb4-8fc2-5beaae59e127"));
  • Related