I've run into a problem while testing an Azure Function which runs on top of Azure Tables: How can I fake the result of a table query which returns an AsyncPageable
?
Here's the code under test...
public async Task<Project?> GetProjectByIdAsync(Guid projectId)
{
const int maxResultsPerPage = 1;
IEnumerable<string>? selectProps = null;
// _projectsTableService is an ITableService.
var tableClient = _projectsTableService.GetTableClient();
var results = tableClient.QueryAsync<Project>(project => project.Id.Equals(projectId),
maxResultsPerPage,
selectProps,
CancellationToken.None);
await foreach (var result in results)
{
return result;
}
return null;
}
And here's my work-in-progress test method...
[TestInitialize]
public void TestInit()
{
_project = new Project { Id = Guid.NewGuid() };
_tableClient = A.Fake<TableClient>();
_tableService = A.Fake<ITableService>();
_tableServiceFactory = A.Fake<ITableServiceFactory>();
A.CallTo(() => _tableService.GetTableClient()).Returns(_tableClient);
A.CallTo(() => _tableServiceFactory.Create(TableName)).Returns(_tableService);
_testee = new ProjectsTableService(_tableServiceFactory);
}
[TestMethod]
public async Task GetProjectByIdAsync_WhenMatchingProjectFound_ReturnsProject()
{
var projectId = Guid.NewGuid();
var project = new Project { Id = projectId };
var projectsResult = new List<Project> { _project };
var asyncPageable = A.Fake<AsyncPageable<Project>>();
var enumerator = projectsResult.ToAsyncEnumerable().GetAsyncEnumerator();
A.CallTo(() => asyncPageable.GetAsyncEnumerator(A<CancellationToken>._)).Returns(enumerator);
A.CallTo(() => _tableClient.QueryAsync(A<Expression<Func<Project, bool>>>._,
A<int>._,
A<IEnumerable<string>>._,
A<CancellationToken>._)).Returns(asyncPageable);
var result = await _testee.GetProjectByIdAsync(_project.Id);
result.Should().NotBeNull();
result.Id.Should().Be(projectId);
}
When I step through this test the results
AsyncPageable<Project>
contains no results.
UPDATE
Here's a second attempt based on this example...
[TestMethod]
public async Task GetProjectByIdAsync_WhenMatchingProjectFound_ReturnsProject2()
{
var projectId = Guid.NewGuid();
var project = new Project { Id = projectId };
var projects = new List<Project> { _project };
var page = Page<Project>.FromValues(projects,
continuationToken: null,
response: A.Fake<Response>());
var pages = AsyncPageable<Project>.FromPages(new[] { page });
A.CallTo(() => _tableClient.QueryAsync(A<Expression<Func<Project, bool>>>._,
A<int>._,
A<IEnumerable<string>>._,
A<CancellationToken>._)).Returns(pages);
var result = await _testee.GetProjectByIdAsync(_project.Id);
result.Should().NotBeNull();
result.Id.Should().Be(projectId);
}
Can anyone help me to fake this AsyncPageable
result?
I found out the cause of my problem: As @BlairConrad alluded to in his comment, it was in my initial set-up of the dependencies...
A.CallTo(() => _tableServiceFactory.Create(TableName)).Returns(_tableService);
The TableName
member differs between my test class and the implementation. I'm still not sure why I was getting any faked objects, but that's a secondary question.
So I now have a working test using code found in the post lined by @PeterBons', which is shown in the update in the OP.