es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

¿Cómo puedo probar una política de reintento de Polly que está configurada durante el inicio?

Durante el inicio, básicamente agrego un HttpClient así:

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($"Error con código de estado {result.Result.StatusCode}. Intento de reintentar {retryAttempt}. Reintentando en {timespan}.");
            }));
}

¿Cómo puedo probar que la política de reintento funciona como se espera? He intentado escribir una prueba como esta:

public async Task MyTest()
{
    var policy = GetMockRetryPolicy(); // devuelve la política mostrada anteriormente.
    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);

    // Algunas afirmaciones que no funcionan en este momento
}

Para referencia, aquí está la mayor parte de mi método Post en MyFakeClient:

if(Enum.TryParse(content.ToString(), out HttpStatusCode statusCode))
{
    if(statusCode == HttpStatusCode.InternalServerError)
    {
        throw new HttpResponseException(new Exception("Error interno del servidor"), (int)HttpStatusCode.InternalServerError);
    }
}

El MyFakeClient tiene un método Post que comprueba si el contenido es un HttpStatusCode y si es un error interno del servidor, lanza una excepción HttpResponseException. En este momento, esto crea el cliente correcto y desencadena la publicación correctamente. Lanza la HttpResponseException, pero al hacerlo sale de la prueba en lugar de usar la política de reintento.

¿Cómo puedo hacer que use la política de reintento en la prueba?

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Para probar que la política de reintento funcione como se espera, podría probar lo siguiente:

    1. En lugar de usar un cliente falso, intente usar un controlador de delegado de prueba para simular el comportamiento de HttpClient. Puede crear una clase simple que herede de DelegatingHandler y anular el método SendAsync para devolver una respuesta con el código de estado deseado (por ejemplo, HttpStatusCode.InternalServerError) para las primeras X solicitudes (donde X es el número de reintentos que desea probar), y luego devolver una respuesta exitosa para solicitudes posteriores. Esto simulará el comportamiento de error transitorio que la política de reintento debe manejar.
    2. En su método de prueba, cree un HttpClient con el controlador de delegación de prueba y páselo a su implementación de MyHttpClient. Luego, llame al método Post y asegúrese de que reintente el número correcto de veces y eventualmente tenga éxito. Puede usar una biblioteca como FluentAssertions para hacer que sus afirmaciones sean más legibles.

    Código de prueba de ejemplo (usando NUnit y FluentAssertions):

    [Test]
    public async Task MyTest()
    {
        const int maxRetries = 3;
        var handler = new StubHandler(maxRetries, HttpStatusCode.InternalServerError);
        var httpClient = new HttpClient(handler);
        var myHttpClient = new MyHttpClient(httpClient);
    
        var result = await myHttpClient.Post(new Uri("https://someurl.com"), HttpStatusCode.InternalServerError);
    
        result.Should().Be(HttpStatusCode.OK);
        handler.RetryCount.Should().Be(maxRetries + 1); // Espera 4 llamadas en total (1 original, 3 reintentos)
    }
    

    Tenga en cuenta que este enfoque implica una prueba de integración en lugar de una prueba de unidad, ya que requiere una instancia real de HttpClient y conectividad de red. Sin embargo, proporciona una simulación más precisa del comportamiento de HttpClient y le permite probar la política de reintento sin depender de detalles de implementación de HttpClient en sí.

Comments are closed.