Linq 能够使用查询表达式的模拟IDocumentQuery

Linq 能够使用查询表达式的模拟IDocumentQuery,linq,azure-cosmosdb,nsubstitute,Linq,Azure Cosmosdb,Nsubstitute,我需要能够模拟IDocumentQuery,能够测试查询文档集合并可能使用谓词过滤它们的代码段: IQueryable<T> documentQuery = client .CreateDocumentQuery<T>(collectionUri, options); if (predicate != null) { documentQuery = documentQuery.Where(predicate); } var lis

我需要能够模拟
IDocumentQuery
,能够测试查询文档集合并可能使用谓词过滤它们的代码段:

IQueryable<T> documentQuery = client
                .CreateDocumentQuery<T>(collectionUri, options);

if (predicate != null)
{
   documentQuery = documentQuery.Where(predicate);
}

var list = documentQuery.AsDocumentQuery();
var documents = new List<T>();           

while (list.HasMoreResults)
{
   documents.AddRange(await list.ExecuteNextAsync<T>());
}
IQueryable documentQuery=客户端
.CreateDocumentQuery(collectionUri,选项);
if(谓词!=null)
{
documentQuery=documentQuery.Where(谓词);
}
var list=documentQuery.AsDocumentQuery();
var documents=新列表();
while(list.HasMoreResults)
{
documents.AddRange(wait list.ExecuteNextAsync());
}
我使用了来自的答案来编写以下方法:

public static IDocumentClient Create<T>(params T[] collectionDocuments)
{
    var query = Substitute.For<IFakeDocumentQuery<T>>();

    var provider = Substitute.For<IQueryProvider>();

    provider
        .CreateQuery<T>(Arg.Any<Expression>())                                                
        .Returns(x => query);

    query.Provider.Returns(provider);
    query.ElementType.Returns(collectionDocuments.AsQueryable().ElementType);
    query.Expression.Returns(collectionDocuments.AsQueryable().Expression);
    query.GetEnumerator().Returns(collectionDocuments.AsQueryable().GetEnumerator());

    query.ExecuteNextAsync<T>().Returns(x => new FeedResponse<T>(collectionDocuments));
    query.HasMoreResults.Returns(true, false);

    var client = Substitute.For<IDocumentClient>();

    client
        .CreateDocumentQuery<T>(Arg.Any<Uri>(), Arg.Any<FeedOptions>())
        .Returns(query);

    return client;
}
公共静态IDocumentClient创建(参数T[]collectionDocuments)
{
var query=Substitute.For();
var provider=Substitute.For();
供应商
.CreateQuery(Arg.Any())
.Returns(x=>query);
query.Provider.Returns(Provider);
返回(collectionDocuments.AsQueryable().ElementType);
Expression.Returns(collectionDocuments.AsQueryable().Expression);
query.GetEnumerator().Returns(collectionDocuments.AsQueryable().GetEnumerator());
返回(x=>newfeedresponse(collectionDocuments));
query.HasMoreResults.Returns(true、false);
var client=Substitute.For();
客户
.CreateDocumentQuery(Arg.Any(),Arg.Any())
.返回(查询);
返回客户;
}
只要不使用
IQueryable.Where
进行过滤,它就可以正常工作

我的问题:

是否有任何方法可以捕获用于创建
documentQuery
并将该谓词应用于
collectionDocuments
参数的谓词


从查询提供程序访问表达式,以便将其传递到支持集合以应用所需的筛选器

回顾以下内容

public static IDocumentClient Create<T>(params T[] collectionDocuments) {
    var query = Substitute.For<IFakeDocumentQuery<T>>();

    var queryable = collectionDocuments.AsQueryable();

    var provider = Substitute.For<IQueryProvider>();
    provider.CreateQuery<T>(Arg.Any<Expression>())
        .Returns(x => {
            var expression = x.Arg<Expression>();
            if (expression != null) {
                queryable = queryable.Provider.CreateQuery<T>(expression);
            }
            return query;
        });

    query.Provider.Returns(_ => provider);
    query.ElementType.Returns(_ => queryable.ElementType);
    query.Expression.Returns(_ => queryable.Expression);
    query.GetEnumerator().Returns(_ => queryable.GetEnumerator());

    query.ExecuteNextAsync<T>().Returns(x => new FeedResponse<T>(query));
    query.HasMoreResults.Returns(true, true, false);

    var client = Substitute.For<IDocumentClient>();

    client
        .CreateDocumentQuery<T>(Arg.Any<Uri>(), Arg.Any<FeedOptions>())
        .Returns(query);

    return client;
}
公共静态IDocumentClient创建(参数T[]collectionDocuments){
var query=Substitute.For();
var queryable=collectionDocuments.AsQueryable();
var provider=Substitute.For();
CreateQuery(Arg.Any())
.Returns(x=>{
var表达式=x.Arg();
if(表达式!=null){
queryable=queryable.Provider.CreateQuery(表达式);
}
返回查询;
});
返回(=>Provider);
返回(=>queryable.ElementType);
Expression.Returns(=>queryable.Expression);
query.GetEnumerator().Returns(=>queryable.GetEnumerator());
ExecuteNextAsync().返回(x=>newfeedresponse(query));
query.HasMoreResults.Returns(true、true、false);
var client=Substitute.For();
客户
.CreateDocumentQuery(Arg.Any(),Arg.Any())
.返回(查询);
返回客户;
}
重要的部分是,传递给查询的表达式用于在备份数据源(数组)上创建另一个查询

出于演示目的,使用以下示例测试对象

public class SubjectUnderTest {
    private readonly IDocumentClient client;

    public SubjectUnderTest(IDocumentClient client) {
        this.client = client;
    }

    public async Task<List<T>> Query<T>(Expression<Func<T, bool>> predicate = null) {
        FeedOptions options = null; //for dummy purposes only
        Uri collectionUri = null;  //for dummy purposes only
        IQueryable<T> documentQuery = client.CreateDocumentQuery<T>(collectionUri, options);

        if (predicate != null) {
            documentQuery = documentQuery.Where(predicate);
        }

        var list = documentQuery.AsDocumentQuery();
        var documents = new List<T>();

        while (list.HasMoreResults) {
            documents.AddRange(await list.ExecuteNextAsync<T>());
        }

        return documents;
    }
}
公共类SubjectUnderTest{
私有只读IDocumentClient客户端;
公共SubjectionTest(IDocumentClient客户端){
this.client=client;
}
公共异步任务查询(表达式谓词=null){
FeedOptions=null;//仅用于虚拟目的
Uri collectionUri=null;//仅用于虚拟目的
IQueryable documentQuery=client.CreateDocumentQuery(collectionUri,选项);
if(谓词!=null){
documentQuery=documentQuery.Where(谓词);
}
var list=documentQuery.AsDocumentQuery();
var documents=新列表();
while(list.HasMoreResults){
documents.AddRange(wait list.ExecuteNextAsync());
}
归还文件;
}
}
以下示例测试将表达式传递到查询时的情况

[TestMethod]
public async Task Should_Filter_DocumentQuery() {
    //Arrange
    var dataSource = Enumerable.Range(0, 3)
        .Select(_ => new Document() { Key = _ }).ToArray();
    var client = Create(dataSource);
    var subject = new SubjectUnderTest(client);

    Expression<Func<Document, bool>> predicate = _ => _.Key == 1;
    var expected = dataSource.Where(predicate.Compile());

    //Act
    var actual = await subject.Query<Document>(predicate);

    //Assert
    actual.Should().BeEquivalentTo(expected);
}

public class Document {
    public int Key { get; set; }
}
[TestMethod]
公共异步任务应该\u Filter\u DocumentQuery(){
//安排
var数据源=可枚举的范围(0,3)
.Select(=>newdocument(){Key=}).ToArray();
var client=Create(数据源);
var subject=新SubjectUnderTest(客户机);
表达式谓词=\u=>\ u0.Key==1;
var expected=dataSource.Where(predicate.Compile());
//表演
var-actual=wait-subject.Query(谓词);
//断言
实际的.Should().beequivalento(预期的);
}
公共类文档{
公共int密钥{get;set;}
}

精彩的答案,我想这是我第一次看到我的问题的答案和解决方案,其中还包括单元测试。谢谢。