我希望对HttpClient
具有 a 的 a进行单元测试Polly
RetryPolicy
,我正在努力研究如何控制HTTP
响应。
我HttpMessageHandler
在客户端上使用了 a ,然后覆盖了发送异步,这很好用,但是当我添加 Polly 重试策略时,我必须使用IServiceCollection
和无法HttpMessageHandler
为客户端创建一个HTTP 客户端实例。我曾尝试使用 ,.AddHttpMessageHandler()
但这会阻止轮询重试策略并且它只触发一次。
这就是我在测试中设置 HTTP 客户端的方式
IServiceCollection services = new ServiceCollection();
const string TestClient = "TestClient";
services.AddHttpClient(name: TestClient)
.AddHttpMessageHandler()
.SetHandlerLifetime(TimeSpan.FromMinutes(5))
.AddPolicyHandler(KYA_GroupService.ProductMessage.ProductMessageHandler.GetRetryPolicy());
HttpClient configuredClient =
services
.BuildServiceProvider()
.GetRequiredService<IHttpClientFactory>()
.CreateClient(TestClient);
public static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy()
{
return HttpPolicyExtensions
.HandleTransientHttpError()
.WaitAndRetryAsync(6,
retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)),
onRetryAsync: OnRetryAsync);
}
private async static Task OnRetryAsync(DelegateResult<HttpResponseMessage> outcome, TimeSpan timespan, int retryCount, Context context)
{
//Log result
}
这将在我调用时触发请求,_httpClient.SendAsync(httpRequestMessage)
但它实际上创建了一个对地址的 Http 调用,我需要以某种方式拦截它并返回受控响应。
我想测试该策略是否用于在请求失败时重试请求并在完成响应时完成。
我的主要限制是我不能在 MSTest 上使用 Moq。
您不希望将HttpClient
真正的 HTTP 请求作为单元测试的一部分发出 - 那将是集成测试。为避免提出真正的请求,您需要提供自定义HttpMessageHandler
. 您已在帖子中规定您不想使用模拟框架,因此HttpMessageHandler
您可以提供一个stub而不是模拟。
由于此评论对 Polly 的 GitHub 页面上的一个问题产生了重大影响,我调整了您的示例以调用 stubbed HttpMessageHandler
,它在第一次调用时抛出 500,然后在后续请求中返回 200。
该测试断言重试处理程序已被调用,并且当执行步骤越过HttpClient.SendAsync
对结果响应的调用时,状态代码为 200:
public class HttpClient_Polly_Test
{
const string TestClient = "TestClient";
private bool _isRetryCalled;
[Fact]
public async Task Given_A_Retry_Policy_Has_Been_Registered_For_A_HttpClient_When_The_HttpRequest_Fails_Then_The_Request_Is_Retried()
{
// Arrange
IServiceCollection services = new ServiceCollection();
_isRetryCalled = false;
services.AddHttpClient(TestClient)
.AddPolicyHandler(GetRetryPolicy())
.AddHttpMessageHandler(() => new StubDelegatingHandler());
HttpClient configuredClient =
services
.BuildServiceProvider()
.GetRequiredService<IHttpClientFactory>()
.CreateClient(TestClient);
// Act
var result = await configuredClient.GetAsync("https://www.stackoverflow.com");
// Assert
Assert.True(_isRetryCalled);
Assert.Equal(HttpStatusCode.OK, result.StatusCode);
}
public IAsyncPolicy<HttpResponseMessage> GetRetryPolicy()
{
return HttpPolicyExtensions.HandleTransientHttpError()
.WaitAndRetryAsync(
6,
retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)),
onRetryAsync: OnRetryAsync);
}
private async Task OnRetryAsync(DelegateResult<HttpResponseMessage> outcome, TimeSpan timespan, int retryCount, Context context)
{
//Log result
_isRetryCalled = true;
}
}
public class StubDelegatingHandler : DelegatingHandler
{
private int _count = 0;
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,
CancellationToken cancellationToken)
{
if (_count == 0)
{
_count++;
return Task.FromResult(new HttpResponseMessage(HttpStatusCode.InternalServerError));
}
return Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK));
}
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句