通过利用MSDN上《使用模拟框架进行测试》文章中异步查询测试部分的链接,我成功创建了许多测试用例。
这是我的测试代码,使用NSubstitute进行模拟:
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()
并没有做太多事情,但它会执行以下查询:
await DataContext.Locations
.GroupBy(l => l.Area)
.ToListAsync());
这个功能在查询中添加投影之前运行良好:
await DataContext.Locations
.GroupBy(l => l.Area)
.Select(l => new LocationsIndexVM{ Area = l.Key }) // added projection
.ToListAsync());
这会导致以下异常:
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
更新: 我已经上传了一个小而简单的解决方案,可重现此问题。有人能提供一个示例来对既是
async
又包含.Select()
投影的查询进行单元测试吗?