模拟IOrderedQueryable和IDocumentQuery

时间:2018-05-24 16:23:41

标签: c# unit-testing mocking azure-cosmosdb linq-expressions

我使用IDocumentClient检索和更新DocumentDB集合中的项目。

检索符合条件的文档列表的代码如下所示:

public static async Task<FeedResponse<T>> GetDocuments<T>(
            this IDocumentClient client,
            string collection,
            Expression<Func<T, bool>> filter)
        {
            IDocumentQuery<T> query = client.CreateDocumentQuery<T>(GetCollectionUri(collection)).Where(filter)
                                            .AsDocumentQuery();
            return await query.ExecuteNextAsync<T>().ConfigureAwait(false);
        }

为了针对模拟项列表对上面的代码进行单元测试,我创建了一个模拟类:

public class MockIOrderedQueryable<T> : List<T>, IOrderedQueryable<T>, IDocumentQuery<T>
    {
        public Expression Expression
        {
            get
            {
                var content = this.ToList();
                return content.AsQueryable().Expression;
            }
        }

        public IQueryProvider Provider => new MyProvider<T>(this.ToList());

        public Task<FeedResponse<TResult>> ExecuteNextAsync<TResult>(CancellationToken token = new CancellationToken())
        {
            var tmp = new FeedResponse<TResult>((IEnumerable<TResult>)this);
            return Task.FromResult(tmp);
        }    
    }

Where过滤器是IQueryable<T>上的扩展方法,因此我需要一个如下所示的实现:

public class MyQueryable<T> : IQueryable<T>, IDocumentQuery<T>
    {
        private readonly List<T> _list;

        public MyQueryable(List<T> list)
        {
            _list = list;
        }

        public Task<FeedResponse<TResult>> ExecuteNextAsync<TResult>(CancellationToken token = new CancellationToken())
        {
            var tmp = new FeedResponse<TResult>(_list as List<TResult>);
            return Task.FromResult(tmp);            
        }    
    }

还有IQueryProvider的实现,它通过IQueryableCreateQuery实例返回到我原来的模拟类:

public class MyProvider<T> : IQueryProvider
    {
        private readonly List<T> _list;

        public MyProvider(List<T> list)
        {
            _list = list;
        }

        public IQueryable<TElement> CreateQuery<TElement>(Expression expression)
        {
            return new MyQueryable<TElement>(_list as List<TElement>);
        }        
    }

为简洁起见,我省略了抛出NotImplementedException的方法的代码以及未使用的字段的代码。

这一切看起来都不错,但有一点我无法做到:将ExpressionCreateQuery传递的真实过滤应用于_list MyProvider成员{1}}。我试着调用Invoke并检索参数,但它没有用。 MockIOrderedQueryable中返回的表达式可能不是好的(.AsQueryable列表中的表达式)。我想找到一个lambda Expression<Func<T, bool>>并在列表中调用它。

任何帮助表示感谢。

0 个答案:

没有答案