Testing EF async methods with sync methods with MOQ

回眸只為那壹抹淺笑 提交于 2019-12-03 10:16:20

The EnumerableQuery<T> class which is produced by .AsQueryable() does not implement IDbAsyncQueryProvider but it's easy to extend EnumerableQuery<T> with the implementation. Create one of these instead of calling .AsQueryable() to wrap your collection. I have an implementation below that extends it further into a IDbSet<T> but you may not need to go that far.

class StubSet<T> : EnumerableQuery<T>, IDbSet<T>, IDbAsyncQueryProvider
    where T : class
{
    public StubSet(IEnumerable<T> collection) : base(collection)
    {
        Local = new ObservableCollection<T>(collection);
    }

    public ObservableCollection<T> Local { get; private set; }

    public T Find(params object[] keyValues)
    {
        throw new NotImplementedException();
    }

    public T Add(T entity)
    {
        Local.Add(entity);
        return entity;
    }

    public T Remove(T entity)
    {
        Local.Remove(entity);
        return entity;
    }

    public T Attach(T entity)
    {
        return Add(entity);
    }

    public T Create()
    {
        throw new NotImplementedException();
    }

    public TDerivedEntity Create<TDerivedEntity>() where TDerivedEntity : class, T
    {
        throw new NotImplementedException();
    }

    public void DeleteObject(T entity)
    {
        throw new NotImplementedException();
    }

    public void Detach(T entity)
    {
        throw new NotImplementedException();
    }        

    async Task<object> IDbAsyncQueryProvider.ExecuteAsync(Expression expression, CancellationToken cancellationToken)
    {
        return ((IQueryProvider)this).Execute(expression);
    }

    async Task<TResult> IDbAsyncQueryProvider.ExecuteAsync<TResult>(Expression expression, CancellationToken cancellationToken)
    {
        return ((IQueryProvider)this).Execute<TResult>(expression);
    }
}

Maybe this post comes a bit late but anyway :)

I recommend you to use this library: https://www.nuget.org/packages/EntityFrameworkTesting/

Here is the GitHub Project: https://github.com/scott-xu/EntityFramework.Testing

Please remember to make all your DbSets virtual!

In case you want to use FindAsync you need to provide a "Func" delegate in "SetupData" method

ex:

var mockDbSetDisplays = new Mock<DbSet<DbEntity>>().SetupData(dataSourceDisplays, this.FindDisplay);

.....

private Display FindDisplay(object[] arg)
{
  return this.dataSourceDisplays.FirstOrDefault(x=> x.DisplayId == arg[0] as int?);
}

Here you can see how this library mocks the FindAsync:

https://github.com/scott-xu/EntityFramework.Testing/blob/master/src/EntityFramework.Testing.Moq/MoqDbSetExtensions.cs

Hope this can be useful for someone!

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!