在启动期间,我基本上会像这样添加一个 HttpClient
:
services.AddHttpClient<IHttpClient, MyHttpClient>().AddPolicyHandler(GetRetryPolicy());
public IAsyncPolicy<HttpResponseMessage> GetRetryPolicy()
{
HttpPolicyExtensions
.HandleTransientHttpError()
.OrResult(message => message.StatusCode == HttpStatusCode.NotFound)
.WaitAndRetryAsync(GetBackOffDelay(options),
onRetry: (result, timespan, retryAttempt, context) =>
{
context.GetLogger()?.LogWarning($"Failure with status code {result.Result.StatusCode}. Retry attempt {retryAttempt}. Retrying in {timespan}.");
}));
}
如何测试重试策略是否按预期工作?我尝试编写了以下测试:
public async Task MyTest()
{
var policy = GetMockRetryPolicy(); // returns the policy shown above.
var content = HttpStatusCode.InternalServerError;
var services = new ServiceCollection();
services.AddHttpClient<IHttpClient, MyFakeClient>()
.AddPolicyHandler(policy);
var client = (MyFakeClient)services.BuildServiceProvider().GetRequiredService<IHttpClient>();
await client.Post(new Uri("https://someurl.com")), content);
// Some asserts that don't work right now
}
以下是 MyFakeClient
的Post
方法的主体代码:
if(Enum.TryParse(content.ToString(), out HttpStatusCode statusCode))
{
if(statusCode == HttpStatusCode.InternalServerError)
{
throw new HttpResponseException(new Exception("Internal Server Error"), (int)HttpStatusCode.InternalServerError);
}
}
MyFakeClient
有一个 Post
方法,它会检查内容是否为 HttpStatusCode
,如果是内部服务器错误就会抛出一个 HttpResponseException
。目前,这样创建了正确的客户端并触发了 post 操作。但它抛出了 HttpResponseException
,同时退出测试,而没有使用重试策略。如何使它在测试中使用重试策略?
更新: 我遵循 Peter 的建议,采用集成测试方法,并通过 hostbuilder 和存根委托处理程序将其运行成功。在存根处理程序中,我传递了一个自定义标头,以便能够从响应中读取重试计数。重试计数实际上是处理程序上的一个属性,每次调用时都会增加,因此它是第一次尝试加上所有后续重试的次数。这意味着如果重试计数为 3,则您应该期望值为 4。