0

I am attempting to mock out some of EF Core's functions.

Originally I was getting the following error

The provider for the source IQueryable doesn't implement IAsyncQueryProvider. Only providers that implement IEntityQueryProvider can be used for Entity Framework asynchronous operations.

After looking at this question it almost seems to work but i'm now getting the following:

System.ArgumentNullException : Value cannot be null. Parameter name: source at Microsoft.EntityFrameworkCore.Utilities.Check.NotNull[T](T value, String parameterName) at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.FirstOrDefaultAsync[TSource](IQueryable1 source, Expression1 predicate, CancellationToken cancellationToken) at Ombi.Core.Rule.Rules.Search.RadarrCacheRule.d__2.MoveNext() in C:\Users\Jamie.Rees\Source\Repos\PlexRequests.Net\src\Ombi.Core\Rule\Rules\Search\RadarrCacheRule.cs:line 25

Here is the test code:

[Test]
public async Task Should_ReturnApproved_WhenMovieIsInRadarr()
{
    var list = new List<RadarrCache>(){new RadarrCache
    {
        TheMovieDbId = 123
    }}.AsQueryable();
    var radarrMock = new Mock<DbSet<RadarrCache>>();
    radarrMock.As<IAsyncEnumerable<RadarrCache>>()
        .Setup(m => m.GetEnumerator())
        .Returns(new TestAsyncEnumerator<RadarrCache>(list.GetEnumerator()));


    radarrMock.As<IQueryable<RadarrCache>>()
        .Setup(m => m.Provider)
        .Returns(new TestAsyncQueryProvider<RadarrCache>(list.Provider));

    radarrMock.As<IQueryable<RadarrCache>>().Setup(m => m.Expression).Returns(list.Expression);
    radarrMock.As<IQueryable<RadarrCache>>().Setup(m => m.ElementType).Returns(list.ElementType);
    radarrMock.As<IQueryable<RadarrCache>>().Setup(m => m.GetEnumerator()).Returns(() => list.GetEnumerator());


    ContextMock.Setup(c => c.Set<RadarrCache>()).Returns(radarrMock.Object);

    var request = new SearchMovieViewModel { Id = 123 };
    var result =await  Rule.Execute(request);

    Assert.True(result.Success);
    Assert.True(request.Approved);
}

This is the class under test:

public class RadarrCacheRule : BaseSearchRule, IRules<SearchViewModel>
{
    public RadarrCacheRule(IOmbiContext ctx)
    {
        _ctx = ctx;
    }

    private readonly IOmbiContext _ctx;

    public async Task<RuleResult> Execute(SearchViewModel obj)
    {
        if (obj.Type == RequestType.Movie)
        {
            // Check if it's in Radarr
            var result = await _ctx.RadarrCache.FirstOrDefaultAsync(x => x.TheMovieDbId == obj.Id);
            if (result != null)
            {
                obj.Approved =
                    true; // It's in radarr so it's approved... Maybe have a new property called "Processing" or something?
            }
        }
        return Success();
    }
}

Any idea how I am suppose to do this?

Jamie Rees
  • 7,973
  • 2
  • 45
  • 83
  • 1
    `new Mock>()` ... looks like you are using MOQ. If yes then MOQ doesn't support *Shims* and thus mostly your mocking here won't work – Rahul Oct 17 '17 at 11:57
  • 1
    You don't use EF Core in Unit Tests due to this. You either abstract EF Core away (in repositories or CQRS) and then mock it or you use InMemory EF Core (or EF Core Sqlite in memory DB if you need closer behaviour to a real relational database) in an integration test (and not a unit test) – Tseng Oct 17 '17 at 11:57
  • 1
    or better yet, don't use EF at all in any flavour. If you must ORM, there are many extremely capable microORMS which operate quicker, still let you write decent sprocs and don't spam horrible SQL at your database. – Rich Bryant Oct 17 '17 at 12:10
  • You can have a look at my implementation of Moq/NSubstitute/FakeItEasy extension MockQueryable: https://github.com/romantitov/MockQueryable/tree/master/src/MockQueryable/MockQueryable – R.Titov Dec 24 '19 at 12:42

0 Answers0