Follow instructions from Testing with a mocking framework, I can mock Async function for DBSet like CountAsync..., but exception "InvalidOperationException: The source IQueryable
doesn't implement IDbAsyncEnumerable<OrderSummary>
" is throwed when I write to return with anonymous or custom type. Any solution to perform it?
My mocking
public class DbContextBuilderFixture : IDisposable
{
protected readonly Mock<DbSet<Item>> MockDbSetItem = new Mock<DbSet<Item>>();
public DbContextBuilderFixture()
{
}
public ShopingContext Build()
{
var mockContext = new Mock<ShopingContext>();
mockContext.Setup(t=>t.Items).Returns(() => MockDbSetItem.Object);
return mockContext.Object;
}
public Mock<DbSet<Item>> WithItems(List<Item> items)
{
var data = stockTakes.AsQueryable();
MockDbSetItem.As<IDbAsyncEnumerable<Item>>()
.Setup(m => m.GetAsyncEnumerator())
.Returns(new DbAsyncEnumeratorHelper<Item>(data.GetEnumerator()));
MockDbSetItem.As<IQueryable<Item>>()
.Setup(m => m.Provider)
.Returns(new DbAsyncQueryProviderHelper<Item>(data.Provider));
MockDbSetItem.As<IQueryable<Item>>().Setup(m => m.Expression).Returns(data.Expression);
MockDbSetItem.As<IQueryable<Item>>().Setup(m => m.ElementType).Returns(data.ElementType);
MockDbSetItem.As<IQueryable<Item>>().Setup(m => m.GetEnumerator()).Returns(data.GetEnumerator());
return MockDbSetItem;
}
public void Dispose()
{
MockDbSetItem?.Invocations.Clear();
MockDbSetItem?.Reset();
}
}
My code (Entity Framework 6.0):
Public Taks<Dictionary<int, OrderSummary> GetOrderSummaryAsync()
{
return await Db.Items
.GroupBy(
i => i.OrderId,
i => new
{
i.SubTotal,
i.Quantity
},
(key, g) => new OrderSummary
{
Id = key,
Total = g.Sum(i => i.SubTotal),
TotalCount = g.Sum(i => i.Quantity)
})
.ToDictionaryAsync(i => i.Id);
}
My Unitest
[Fact]
public void GetOrderSumamry_ShouldCorrectTotalCount()
{
//arrange
var listItem = new List<Item>
{
BuilderItem.Default()
.WithId(1)
.WithOrderId(1)
.WithCreatedDate(new DateTime(2021, 10, 20))
.WithSubTotal(1000)
.WithQuantity(200)
.Build(),
BuilderItem.Default()
.WithId(2)
.WithOrderId(1)
.WithCreatedDate(new DateTime(2021, 10, 21))
.WithSubTotal(1000)
.WithQuantity(200)
.Build()
};
DbContext.WithItems(listItem);
var itemService = new ItemService(DbContext.Build());
//action
/*
exception "InvalidOperationException: The source IQueryable doesn't
implement IDbAsyncEnumerable<OrderSummary>"
*/
var orderSummaryDict = itemService.GetOrderSummaryAsync().Result;
//actual
orderSummaryDict[1].TotalCount.Should().Be(400);
}