我正在尝试创建一种方法,可以迭代调用实现分页的 RESTful API 端点,直到找到特定的 JSON 对象。我将在下面概述预期的模式,然后更详细地描述该问题。
// ApiClient.cs
// Example methods that call REST API
public async Task<ICollection<PetsApiResonse>> GetPets(string searchQuery, int skip = 0, int take = 20, bool includeAdopted = false)
{
// Logic that makes HTTP request to something like 'GET {baseUri}/pets'
}
public async Task<ICollection<EmployeesApiResonse>> GetEmployees(string searchQuery, int skip = 0, int take = 20)
{
// Logic that makes HTTP request to something like 'GET {baseUri}/employees'
}
// RequestHandler.cs
// Example method expecting Func<> that doesn't work yet
public static async Task<T> PagedLookupAsync<T>(Func<Task<PetShopApiResponse<ICollection<T>>>> getResponse, string propertyToCompare, object valueToCompare, int maxIterations = 10)
{
Type type = typeof(T);
PropertyInfo propertyInfo = type.GetProperty(propertyToCompare);
ICollection<T> response;
do
{
// This is where I want to alter the 'skip' parameter's value so that each iteration observes a different page from the API
response = await getResponse();
maxIterations--;
}
while (maxIterations >= 0 && !response.Any(o => valueToCompare.Equals(propertyInfo.GetValue(o))));
return response.FirstOrDefault(o => valueToCompare.Equals(propertyInfo.GetValue(o)));
}
// Example code that might be in the body of an NUnit test case
var petIdToFind = "123";
var response = RequestHandler.PagedLookupAsync(ApiClient.GetPetsAsync("sparky", take: 50), nameof(PetsApiResonse.Id), petIdToFind);
response.Result.Should().NotBeNull();
response.Result.Id.Should().BeEquivalentTo(petIdToFind);
您可能已经猜到,目标是测试记录是否存在且可搜索。问题是搜索并不总是在结果的第一页中返回所需的记录,这导致测试不稳定。明显的途径是简单地在需要此功能的每个测试用例中编写循环,但我希望有一种方法可以集中逻辑。
skip
表示页面开始,take
表示页面大小。一种方法是在回调中简单地包含分页参数
skip
和 take
:
public delegate Task<ICollection<T>> GetResponse<T>(int skip, int take);
public static async Task<T> PagedLookupAsync<T>(
GetResponse<T> getResponse,
string propertyToCompare,
object valueToCompare,
int maxIterations = 10,
take = 20
)
{
Type type = typeof(T);
PropertyInfo propertyInfo = type.GetProperty(propertyToCompare);
ICollection<T> response;
int skip = 0;
do
{
// This is where I want to alter the 'skip' parameter's value so that each iteration observes a different page from the API
response = await getResponse(skip, take);
skip += take;
maxIterations--;
}
while (maxIterations >= 0 && !response.Any(o => valueToCompare.Equals(propertyInfo.GetValue(o))));
return response.FirstOrDefault(o => valueToCompare.Equals(propertyInfo.GetValue(o)));
}
然后这样称呼它:
var response = RequestHandler.PagedLookupAsync((skip, take) => ApiClient.GetPetsAsync("sparky", skip, take), nameof(PetsApiResonse.Id), petIdToFind, take: 50);