我从新的 CosmosDb 模拟器中获得了一种执行基本 DocumentDb 操作的存储库,将该存储库注入到其他类中。我想对一个基本查询进行单元测试。
public class DocumentDBRepository<T> where T : class
{
//Details ommited...
public IQueryable<T> GetQueryable()
{
return _client.CreateDocumentQuery<T>(
UriFactory.CreateDocumentCollectionUri(_databaseId, _collectionId),
new FeedOptions { MaxItemCount = -1, EnableCrossPartitionQuery = true });
}
public async Task<IEnumerable<T>> ExecuteQueryAsync(IQueryable<T> query)
{
IDocumentQuery<T> documentQuery = query.AsDocumentQuery();
List<T> results = new List<T>();
while (documentQuery.HasMoreResults)
{
results.AddRange(await documentQuery.ExecuteNextAsync<T>());
}
return results;
}
}
这个代码库需要一个文档客户端来工作,该客户端也会在构造函数中注入。
public DocumentDBRepository(string databaseId, IDocumentClient client)
{
_client = client;
_databaseId = databaseId;
_collectionId = GetCollectionName();
}
我的初始方法是使用CosmosDb模拟器,但这需要运行模拟器,我不喜欢它,而且会使测试变慢。
我的第二种方法是尝试使用文档客户端的模拟。
var data = new List<MyDocumentClass>
{
new MyDocumentClass{ Description= "BBB" },
new MyDocumentClass{ Description= "ZZZ" },
}
.AsQueryable()
.OrderBy(q => q.Description);
var client = new Mock<IDocumentClient>();
client.As<IDocumentClient>()
.Setup(foo => foo.CreateDocumentQuery<MyDocumentClass>(It.IsAny<Uri>(), It.IsAny<FeedOptions>()))
.Returns(data);
DocumentDBRepository<MyDocumentClass> repo= new DocumentDBRepository<MyDocumentClass>(cosmosDatabase, client.Object);
这个仓库所使用的代码工作方式如下:
var query = _documentsRepository.GetQueryable()
.Where(d => d.Description = description)
.OrderByDescending(d => d.description)
.Take(100);
//Execute query async fails.
var result = await _documentsRepository.ExecuteQueryAsync(query);
它失败的原因是,存储库试图将 IQueryable
转换为 IDocumentQuery
对象,这对于 DocumentDb api 是非常特定的(请参见上面的 ExecuteQueryAsync
方法)。之后,它在其上执行 HasMoreResults
方法。所以问题在于,即使我模拟了 .asDocumentQuery()
返回我的对象,我也不知道如何为 HasMoreResults
和 ExecuteNextAsync
提供合理的结果,以便对我的单元测试有意义。
我的第三个选项是直接模拟我的存储库而不是 DocumentClient 对象。 我认为这会更简单,但我不会测试 DocumentDb api 的很多内容。
AsDocumentQuery
方法的主体内容。很可能只需模拟IDocumentQuery<T>
,并对所有标准的IQueryable
方法调用基础的List<T>().AsQuyerable()
。如果你添加了AsDocumentQuery
的列表,我可以试着去做。 - zaitsman