I did something similar to : How to mock an async repository with Entity Framework Core in one of my unit test project .net core 2.1. Now trying to update it to 3.0 preview and have some error with IAsyncQueryProvider.
So when I updated my project. i had some issue with my unit tests. In fact,IAsyncEnumerable switched GetEnumerator for GetAsyncEnumerator. Fixed that. Moreovere some interfaces changed and had to be implemented in my code.
My issue here its with IAsyncQueryProvider witch added TResult IAsyncQueryProvider.ExecuteAsync(Expression expression, CancellationToken cancellationToken) and i don't know what to do with this because since I updated to getAsyncEnumerator i go in this part of my code and can t make it work because i don't know how to return TResult
I've tried:
return Execute<TResult>(expression);
return _inner.Execute<TResult>(expression);
throw new NotImplementedException();(:p sorry had to)
internal class TestAsyncQueryProvider<TEntity> : IAsyncQueryProvider
{
private readonly IQueryProvider _inner;
internal TestAsyncQueryProvider(IQueryProvider inner)
{
_inner = inner;
}
public IQueryable CreateQuery(Expression expression)
{
return new TestAsyncEnumerable<TEntity>(expression);
}
public IQueryable<TElement> CreateQuery<TElement>(Expression expression)
{
return new TestAsyncEnumerable<TElement>(expression);
}
public object Execute(Expression expression)
{
return _inner.Execute(expression);
}
public TResult Execute<TResult>(Expression expression)
{
return _inner.Execute<TResult>(expression);
}
public IAsyncEnumerable<TResult> ExecuteAsync<TResult>(Expression expression)
{
return new TestAsyncEnumerable<TResult>(expression);
}
public Task<TResult> ExecuteAsync<TResult>(Expression expression, CancellationToken cancellationToken)
{
return Task.FromResult(Execute<TResult>(expression));
}
TResult IAsyncQueryProvider.ExecuteAsync<TResult>(Expression expression, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
my test should be passing as it was in .net core 2.1
I've found a library that has successfully upgraded this mock implementation to .NET Core 3.0: https://github.com/romantitov/MockQueryable/blob/master/src/MockQueryable/MockQueryable.EntityFrameworkCore/TestQueryProviderEfCore.cs (note that the code in the github repo has changed since the snippet below was posted).
The interface for Execute
was replaced with ExecuteAsync
in the IdentityServer upgrade.
public TResult ExecuteAsync<TResult>(Expression expression, CancellationToken cancellationToken)
{
var expectedResultType = typeof(TResult).GetGenericArguments()[0];
var executionResult = typeof(IQueryProvider)
.GetMethod(
name: nameof(IQueryProvider.Execute),
genericParameterCount: 1,
types: new[] {typeof(Expression)})
.MakeGenericMethod(expectedResultType)
.Invoke(this, new[] {expression});
return (TResult) typeof(Task).GetMethod(nameof(Task.FromResult))
?.MakeGenericMethod(expectedResultType)
.Invoke(null, new[] {executionResult});
}
The executionResult
is the evaluation of the expression
and then is wrapped in a task (with some reflection to make it generic) Task.FromResult(executionResult)
and returned.
I know this is older but a simpler way to do this is:
public TResult ExecuteAsync<TResult>(Expression expression, CancellationToken cancellationToken = default)
{
var t = Expression.Lambda(expression).Compile().DynamicInvoke();
return Task.FromResult(t as dynamic);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With