Using Testing with asynchronous queries in the article Testing with the Mocking Framework on MSDN , I was able to create many successful tests.
Here is my test code that NSubstitute uses for mocks:
var dummyQueryable = locations.AsQueryable(); var mock = Substitute.For<DbSet<Location>, IDbAsyncEnumerable<Location>, IQueryable<Location>>(); ((IDbAsyncEnumerable<Location>)mock).GetAsyncEnumerator().Returns(new TestDbAsyncEnumerator<Location>(dummyQueryable.GetEnumerator())); ((IQueryable<Location>)mock).Provider.Returns(new TestDbAsyncQueryProvider<Location>(dummyQueryable.Provider)); ((IQueryable<Location>)mock).Expression.Returns(dummyQueryable.Expression); ((IQueryable<Location>)mock).ElementType.Returns(dummyQueryable.ElementType); ((IQueryable<Location>)mock).GetEnumerator().Returns(dummyQueryable.GetEnumerator()); sut.DataContext.Locations = mock; var result = await sut.Index(); result.Should().BeView();
sut.Index() does not do much, but it makes the following request:
await DataContext.Locations .GroupBy(l => l.Area) .ToListAsync());
This works fine until I add a projection to the query:
await DataContext.Locations .GroupBy(l => l.Area) .Select(l => new LocationsIndexVM{ Area = l.Key })
which leads to this exception:
System.InvalidOperationException The source IQueryable doesn't implement IDbAsyncEnumerable<LocationsIndexVM>. Only sources that implement IDbAsyncEnumerable can be used for Entity Framework asynchronous operations. For more details see http://go.microsoft.com/fwlink/?LinkId=287068. at System.Data.Entity.QueryableExtensions.AsDbAsyncEnumerable(IQueryable`1 source) at System.Data.Entity.QueryableExtensions.ToListAsync(IQueryable`1 source) at Example.Web.Controllers.HomeController.<Index>d__0.MoveNext() in HomeController.cs: line 25 --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() at Example.Test.Web.Controllers.HomeControllerShould.<TempTest>d__4.MoveNext() in HomeControllerShould.cs: line 71
UPDATE I downloaded a small, simple solution that reproduces this problem.
Can someone provide an example of what is required for a unit test query, which is like async , and contains a projection .Select() ?
source share