IDbAsyncEnumerable not implemented

前端 未结 7 672
清歌不尽
清歌不尽 2020-12-01 10:50

I am trying to make a FakeDbContext with a FakeDbSet for unit testing.

But I get the following error (see below). I am extending DbSet so normally IDbAsyncEnumerable

相关标签:
7条回答
  • 2020-12-01 10:59

    Just a note for people using the boilerplate code discussed above from Microsoft, here is a quick helper class that can transform your mocked up data into the async result. Just add to the bottom of the MS code and call with something like

    var fakeDateAsMockAsyncQueryResult = new MockAsyncData<SomeType>().MockAsyncQueryResult(fakeDataList.AsQueryable());
    

    .......

    internal class MockAsyncData<T> where T : class
    { 
        public Mock<DbSet<T>> MockAsyncQueryResult(IQueryable<T> data)
        {
            var mockSet = new Mock<DbSet<T>>();
    
            mockSet.As<IDbAsyncEnumerable<T>>()
                .Setup(m => m.GetAsyncEnumerator())
                .Returns(new TestDbAsyncEnumerator<T>(data.GetEnumerator()));
    
            mockSet.As<IQueryable<T>>()
                .Setup(m => m.Provider)
                .Returns(new TestDbAsyncQueryProvider<T>(data.Provider));
    
            mockSet.As<IQueryable<T>>().Setup(m => m.Expression).Returns(data.Expression);
            mockSet.As<IQueryable<T>>().Setup(m => m.ElementType).Returns(data.ElementType);
            mockSet.As<IQueryable<T>>().Setup(m => m.GetEnumerator()).Returns(data.GetEnumerator());
    
            return mockSet;
        }
    }
    

    It's the same code as in the MS example but generic and reusable from many different unit tests.

    0 讨论(0)
  • 2020-12-01 11:02

    In my case the exception was caused by using the wrong ToListAsync extension.

    It came from:

    using System.Data.Entity;
    

    instead of

    using Microsoft.EntityFrameworkCore;
    

    Changing the namespace fixed the error.

    0 讨论(0)
  • 2020-12-01 11:07

    Your scenario is explicitly mentioned in the link provided with the exception message (http://go.microsoft.com/fwlink/?LinkId=287068). The missing ingredient is the IDbAsyncQueryProvider that you should return from your Provider property.

    Just navigate through the link to arrive at the boilerplate implementation.

    Little I can add, I'll just quote the essential phrase:

    In order to use asynchronous queries we need to do a little more work. If we tried to use our Moq DbSet with the GetAllBlogsAsync method we would get the following exception:

    System.InvalidOperationException: The source IQueryable doesn't implement IDbAsyncEnumerable. Only sources that implement IDbAsyncEnumerable can be used for Entity Framework asynchronous operations. For more details see http://go.microsoft.com/fwlink/?LinkId=287068.

    In order to use the async methods we need to create an in-memory DbAsyncQueryProvider to process the async query. Whilst it would be possible to setup a query provider using Moq, it is much easier to create a test double implementation in code. The code for this implementation is as follows:

    etc...

    0 讨论(0)
  • 2020-12-01 11:10

    Not directly related but might help some others. If you're using DelegateCompiler, make sure you're using DecompileAsync rather than Decompile in the EF packages (source).

    0 讨论(0)
  • 2020-12-01 11:14

    DbSet probably implements IDbSet implicitly so that those methods are not available for interface mapping in your derived class.

    Don't derive from IDbSet<TEntity>.

    You cannot call the explicitly implemented interface members of IDbSet from a re-implementation of that interface.

    0 讨论(0)
  • 2020-12-01 11:19

    To solved my IDbAsyncEnumerable issue:

    1. Changed my project's target from .NetFramework 4.0 to .NetFramework 4.5

    2. Reinstalled EntityFramework 6.1.3 Nuget package.

    3. At this point, my Visual Studio's IDE Show Potencial Fixes advisor, allowed me to reference System.Data.Entity.Infrastructure namespace

    using System.Data.Entity.Infrastructure;

    0 讨论(0)
提交回复
热议问题