Reputation: 143
We are using Azure cosmos client V3. For fetching data we are using GetItemLinqQueryable and ToFeedIterator for making it Async. It works well however while mocking/unit testing we are getting error related to ToFeedIterator
Code:
IOrderedQueryable<T> linqQueryable = _container.GetItemLinqQueryable<T>(requestOptions: requestOptions);
var feedIterator = linqQueryable.Where(predicate).ToFeedIterator();
For mocking UnitTestCode Code:
var _mockResponse = new Mock<ItemResponse<Test>>();
mockContainer.Setup(x => x.GetItemLinqQueryable<Test>(It.IsAny<bool>(), It.IsAny<string>(), It.IsAny<QueryRequestOptions>())).Returns(queryable);
It does return 1 records from GetItemLinqQueryable however ToFeedIterator() fails saying System.ArgumentOutOfRangeException: 'ToFeedIterator is only supported on cosmos LINQ query operations Parameter name: linqQuery'
Upvotes: 10
Views: 6756
Reputation: 9789
I too recently had some Cosmos tests I needed working. I followed the linked approach in Scott's answer and came up with the following:
ICosmosLinqQuery.cs
public interface ICosmosLinqQuery
{
FeedIterator<T> GetFeedIterator<T>(IQueryable<T> query);
}
Real implementation of CosmosLinqQuery:
public class CosmosLinqQuery : ICosmosLinqQuery
{
public FeedIterator<T> GetFeedIterator<T>(IQueryable<T> query)
{
return query.ToFeedIterator();
}
}
Example fake implementation with Moq:
var documents = new List<MyDocument>() { myDocument };
var mockFeedResponse = new Mock<FeedResponse<MyDocument>>();
mockFeedResponse.Setup(x => x.GetEnumerator())
.Returns(documents.GetEnumerator());
var mockFeedIterator = new Mock<FeedIterator<MyDocument>>();
mockFeedIterator.SetupSequence(m => m.HasMoreResults).Returns(true).Returns(false);
mockFeedIterator.Setup(m => m.ReadNextAsync(CancellationToken.None)).ReturnsAsync(mockFeedResponse.Object);
var mockCosmosLinqQuery = new Mock<ICosmosLinqQuery>();
mockCosmosLinqQuery.Setup(x => x.GetFeedIterator(query))
.Returns(mockFeedIterator.Object);
The key to ICosmosLinqQuery
is being able to substitute the implementation during testing and inject a real implementation within your application's services.
Registering your real implementation:
services.AddTransient<ICosmosLinqQuery, CosmosLinqQuery>();
Upvotes: 2