Como (devo) simular o DocumentClient para teste de unidade do DocumentDb?
No novo emulador do CosmosDb, eu tenho um repositório para executar operações básicas do documentdb, esse repositório é injetado em outras classes. Eu queria testar uma unidade de uma consulta básica.
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;
}
}
Este repositório precisa de um cliente de documento para funcionar, que também é injetado no construtor.
public DocumentDBRepository(string databaseId, IDocumentClient client)
{
_client = client;
_databaseId = databaseId;
_collectionId = GetCollectionName();
}
Minha abordagem inicial foi usar o emulador CosmosDb, mas isso exigia que o emulador fosse executado, o que eu não gosto e torna os testes mais lentos.
Minha segunda abordagem foi tentar usar uma simulação do cliente de documento.
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);
O código que usa este repositório funciona assim:
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);
Ele falha porque o repositório tenta converter oIQueryable
para umIDocumentQuery
objeto, que é muito específico para a API do DocumentDb (consulte o métodoExecuteQueryAsync
acima). Mais tarde, ele executaHasMoreResults
método nele. Então o problema é que, mesmo que eu zombe.asDocumentQuery()
para retornar meu objeto, não sei como fornecer um resultado paraHasMoreResults
eExecuteNextAsync
para que faça sentido para meus testes de unidade.
Minha terceira opção seria zombar diretamente do meu repositório, em vez do objeto DocumentClient. Acho que seria mais simples, mas não testaria grande parte da API do DocumentDb.