если вы хотите иметь возможность использовать запросы
вого эмулятора 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
объект, который очень специфичен для API DocumentDb (см. методExecuteQueryAsync
выше). Позже он выполняетHasMoreResults
метод на это. Так что проблема, даже если я издеваюсь.asDocumentQuery()
чтобы вернуть мой объект, я не знаю, как обеспечить результат дляHasMoreResults
а такжеExecuteNextAsync
так что это имеет смысл для моих юнит-тестов.
Моим третьим вариантом будет прямое макетирование моего хранилища вместо объекта DocumentClient. Думаю, было бы проще, но я бы не стал тестировать большую часть API DocumentDb.