ICode9

精准搜索请尝试: 精确搜索
首页 > 数据库> 文章详细

c# – 使用SQL查询在单元测试中模拟IDocumentQuery

2019-06-27 11:54:01  阅读:327  来源: 互联网

标签:c unit-testing moq azure azure-cosmosdb


我正在使用单元测试来测试DocumentDBRepository类.我以this post作为SQL查询用例的示例.但它显示错误

Message: System.InvalidCastException : Unable to cast object of type
‘System.Linq.EnumerableQuery
to type
‘Microsoft.Azure.Documents.Linq.IDocumentQuery

这是我的DocumentDBRepository类的代码

private IDocumentQuery<T> GetQueryBySQL(string queryStr)
{
    var uri = UriFactory.CreateDocumentCollectionUri(_databaseId, _collectionId);
    var feedOptions = new FeedOptions { MaxItemCount = -1, EnableCrossPartitionQuery = true };
    IQueryable<T> filter = _client.CreateDocumentQuery<T>(uri, queryStr, feedOptions); 
    IDocumentQuery<T> query = filter.AsDocumentQuery();
    return query;

}

public async Task<IEnumerable<T>> RunQueryAsync(string queryString)
{
    IDocumentQuery<T> query = GetQueryBySQL(queryString);

    List<T> results = new List<T>();

    while (query.HasMoreResults)
    {
        results.AddRange(await query.ExecuteNextAsync<T>());
    }
    return results;
}

这是我的测试类的代码

public async virtual Task Test_GetEntitiesAsyncBySQL()
{
    var id = "100";
    string queryString = "SELECT * FROM c WHERE c.ID = " + id;
    var dataSource = new List<Book> {
            new Book { ID = "100", Title = "abc"}}.AsQueryable();


    Expression<Func<Book, bool>> predicate = t => t.ID == id;
    var expected = dataSource.Where(predicate.Compile());
    var response = new FeedResponse<Book>(expected);

    var mockDocumentQuery = new Mock<DocumentDBRepositoryTest.IFakeDocumentQuery<Book>>();

    mockDocumentQuery
        .SetupSequence(_ => _.HasMoreResults)
        .Returns(true)
        .Returns(false);

    mockDocumentQuery
        .Setup(_ => _.ExecuteNextAsync<Book>(It.IsAny<CancellationToken>()))
        .ReturnsAsync(response);

    var provider = new Mock<IQueryProvider>();
    provider
        .Setup(_ => _.CreateQuery<Book>(It.IsAny<Expression>()))
        .Returns(mockDocumentQuery.Object);

    mockDocumentQuery.As<IQueryable<Book>>().Setup(x => x.Provider).Returns(provider.Object);
    mockDocumentQuery.As<IQueryable<Book>>().Setup(x => x.Expression).Returns(dataSource.Expression);
    mockDocumentQuery.As<IQueryable<Book>>().Setup(x => x.ElementType).Returns(dataSource.ElementType);
    mockDocumentQuery.As<IQueryable<Book>>().Setup(x => x.GetEnumerator()).Returns(() => dataSource.GetEnumerator());

    var client = new Mock<IDocumentClient>();

    client.Setup(_ => _.CreateDocumentQuery<Book>(It.IsAny<Uri>(), It.IsAny<FeedOptions>()))
          .Returns(mockDocumentQuery.Object);

    var documentsRepository = new DocumentDBRepository<Book>(client.Object, "100", "100");

    //Act
    var entities = await documentsRepository.RunQueryAsync(queryString);

    //Assert
    entities.Should()
        .NotBeNullOrEmpty()
        .And.BeEquivalentTo(expected);
}

断点在此代码行停止:

IQueryable<T> filter = _client.CreateDocumentQuery<T>(uri, queryStr, feedOptions); 

filter变量在很多属性上显示null异常,当结果视图显示我在测试方法中定义的期望值时,结果视图显示为空.

有任何线索如何修复它?

解决方法:

需要在模拟的客户端上设置正确的CreateDocumentQuery重载.

被测方法使用

IQueryable<T> filter = _client.CreateDocumentQuery<T>(uri, queryStr, feedOptions); 

然而在安排测试时,客户端的设置就像

client
    .Setup(_ => _.CreateDocumentQuery<Book>(It.IsAny<Uri>(), It.IsAny<FeedOptions>()))
    .Returns(mockDocumentQuery.Object);

应该改为

client
    .Setup(_ => _.CreateDocumentQuery<Book>(It.IsAny<Uri>(), It.IsAny<string>(), It.IsAny<FeedOptions>()))
    .Returns(mockDocumentQuery.Object);

因为有额外的queryStr参数.它也可以直接使用字符串参数作为替代,因为它被明确地注入到方法中并且可以用作期望的一部分.

client
    .Setup(_ => _.CreateDocumentQuery<Book>(It.IsAny<Uri>(), queryStr, It.IsAny<FeedOptions>()))
    .Returns(mockDocumentQuery.Object);

由于测试中的方法在构建查询时没有直接使用Linq,因此不需要像在本主题的上一次迭代中那样模拟/覆盖查询提供程序

以上是经过上述更改后的完成测试

public async virtual Task Test_GetEntitiesAsyncBySQL() {
    //Arrange
    var id = "100";
    string queryString = "SELECT * FROM c WHERE c.ID = " + id;
    var dataSource = new List<Book> {
        new Book { ID = "100", Title = "abc"}
    }.AsQueryable();

    Expression<Func<Book, bool>> predicate = t => t.ID == id;
    var expected = dataSource.Where(predicate.Compile());
    var response = new FeedResponse<Book>(expected);

    var mockDocumentQuery = new Mock<IFakeDocumentQuery<Book>>();

    mockDocumentQuery
        .SetupSequence(_ => _.HasMoreResults)
        .Returns(true)
        .Returns(false);

    mockDocumentQuery
        .Setup(_ => _.ExecuteNextAsync<Book>(It.IsAny<CancellationToken>()))
        .ReturnsAsync(response);

    //Note the change here
    mockDocumentQuery.As<IQueryable<Book>>().Setup(_ => _.Provider).Returns(dataSource.Provider);
    mockDocumentQuery.As<IQueryable<Book>>().Setup(_ => _.Expression).Returns(dataSource.Expression);
    mockDocumentQuery.As<IQueryable<Book>>().Setup(_ => _.ElementType).Returns(dataSource.ElementType);
    mockDocumentQuery.As<IQueryable<Book>>().Setup(_ => _.GetEnumerator()).Returns(() => dataSource.GetEnumerator());

    var client = new Mock<IDocumentClient>();

    //Note the change here
    client
        .Setup(_ => _.CreateDocumentQuery<Book>(It.IsAny<Uri>(), It.IsAny<string>(), It.IsAny<FeedOptions>()))
        .Returns(mockDocumentQuery.Object);

    var documentsRepository = new DocumentDBRepository<Book>(client.Object, "100", "100");

    //Act
    var entities = await documentsRepository.RunQueryAsync(queryString);

    //Assert
    entities.Should()
        .NotBeNullOrEmpty()
        .And.BeEquivalentTo(expected);
}

标签:c,unit-testing,moq,azure,azure-cosmosdb
来源: https://codeday.me/bug/20190627/1304474.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有