【发布时间】:2021-12-02 16:47:03
【问题描述】:
在启动过程中,我基本上添加了一个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。目前,这会创建正确的客户端并触发帖子。它会抛出HttpResponseException,但这样做会退出测试而不是使用重试策略。
如何让它在测试中使用重试策略?
更新
我听从了 Peter 的建议,沿着集成测试路线走下去,并设法使用 hostbuilder 和 stub 委托处理程序使其工作。在存根处理程序中,我传入了一个自定义标头,以使我能够从响应中读取重试计数。重试计数只是处理程序上的一个属性,每次调用时都会增加,所以它实际上是第一次尝试,加上所有后续重试。这意味着如果重试次数为 3,那么您应该期望 4 作为值。
【问题讨论】:
-
也许您可以使用 Testserver 类在内存中创建一个完整的正在运行的 Web 应用程序并使用真实的 http 请求对其进行测试?
标签: c# unit-testing httpclient polly