2

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);
}

  • Anonymous part is covered in [duplicate](https://stackoverflow.com/questions/39416561/moq-a-function-with-anonymous-type) I picked - it simply expected not to work. It is unclear what code you have for non-anonymous part of problem - if that is the case review [MCVE] guidance on posting code and [edit] question so it can be re-opened. – Alexei Levenkov Oct 27 '21 at 18:20
  • Thank you, I'll try clear my code and re-open may question. – khinhvuphiduong Oct 27 '21 at 18:34
  • Dear, @AlexeiLevenkov, I had edit my code and title for extra information and cleary, please re-open my question. Thank you! – khinhvuphiduong Oct 28 '21 at 02:16
  • Since you've edited question after closure it is placed in re-open queue and will eventually be reviewed to be re-opened. I definitely don't see any reason to re-open it yet as question claims it is about unit testing and mocking but there is not a single line of code that shows it. You believe that code shown in the question is [MCVE] of the problem showing all code necessary to reproduce the issue - unfortunately it is hard to see with just code shown how that exception can be thrown by this code. While formally speaking you simply need to wait for review to finish, I advise to edit code... – Alexei Levenkov Oct 28 '21 at 02:29
  • Dear @AlexeiLevenkov, I has reproduced my issue, I hope it's should be clearer, and ready for re-open. Thank for you patience. – khinhvuphiduong Oct 28 '21 at 07:00

0 Answers0