MockQueryable icon indicating copy to clipboard operation
MockQueryable copied to clipboard

Not suported with EF6: BulkUpdateAsync, BulkDeleteAsync, SingleUpdateAsync.

Open DianaGumar opened this issue 3 years ago • 1 comments

Hi Guys. I use MockQueryable approach for EF async methods testing. But I've noticed that it doesn't work for async methods for collections, exactly 'bulk extensions': https://entityframework-extensions.net/bulk-update

Message:  System.AggregateException : One or more errors occurred. (Field '_queryCompiler' defined on type 'Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider' is not a field on the target object which is of type 'TestAsyncEnumerableEfCore[TEntity]'.) ---- System.ArgumentException : Field '_queryCompiler' defined on type 'Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider' is not a field on the target object which is of type 'TestAsyncEnumerableEfCore[TEntity]'.

After some investigation, I found out that Bulk extensions methods require using EntityQueryProvider as provider and IQueryCompiler as _queryCompiler field.

I use the next code to set up async EF methods for testing:

private Mock<DbSet<TEntity>> DbSetConfigureForAsync<TEntity>(Mock<DbSet<TEntity>> dbSet, IQueryable<TEntity> data)
    where TEntity : class
{
    var enumerable = new TestAsyncEnumerable<TEntity>(data);

    // Configure queryable calls
    dbSet.As<IQueryable<TEntity>>().Setup(m => m.Provider).Returns(enumerable);
    dbSet.As<IQueryable<TEntity>>().Setup(m => m.Expression).Returns(data.Expression);
    dbSet.As<IQueryable<TEntity>>().Setup(m => m.ElementType).Returns(data.ElementType);
    dbSet.As<IQueryable<TEntity>>().Setup(m => m.GetEnumerator()).Returns(data.GetEnumerator());

    // Configure async enumerable calls
    dbSet.As<IAsyncEnumerable<TEntity>>()
        .Setup(m => m.GetAsyncEnumerator(It.IsAny<CancellationToken>()))
        .Returns(enumerable?.GetAsyncEnumerator());

    // Configure DbSet calls
    dbSet.Setup(m => m.AsQueryable()).Returns(enumerable); // alternative: _mockSet.Object
    dbSet.Setup(m => m.AsAsyncEnumerable()).Returns(CreateAsyncMock(data));

    return dbSet;
}

Thanks.

DianaGumar avatar Jan 28 '23 23:01 DianaGumar

Hello. Thanks for you contribution. Sorry for the late answer. Unfortunately I'm very busy at the moment. If you provide a pull request with fix of the issue I would be happy to include it to the next release. Please don't forget to cover the case by additional tests to minimize possibility of regressions for the future. Thanks for the understanding.

romantitov avatar Jan 23 '24 18:01 romantitov