Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

198
Visualizações
Inyectar HttpClient de instancia única con HttpMessageHandler específico

Como parte de un proyecto de ASP.Net Core en el que estoy trabajando, tengo el requisito de comunicarme con varios puntos finales de API basados en Rest diferentes desde mi WebApi. Para lograr esto, estoy usando una serie de clases de servicio que instancian un HttpClient estático. Esencialmente, tengo una clase de servicio para cada uno de los puntos finales basados en Rest a los que se conecta WebApi.

A continuación se puede ver un ejemplo de cómo se crea una instancia del HttpClient estático en cada una de las clases de servicio.

 private static HttpClient _client = new HttpClient() { BaseAddress = new Uri("http://endpointurlexample"), };

Si bien lo anterior funciona bien, no permite realizar pruebas unitarias efectivas de las clases de servicio que utilizan HttpClient . Para permitirme llevar a cabo pruebas unitarias, tengo un HttpMessageHandler falso que me gustaría usar para HttpClient en mis pruebas unitarias, mientras que HttpClient se instancia como se indicó anteriormente; sin embargo, no puedo aplicar el HttpMessageHandler falso como parte de mis pruebas unitarias.

¿Cuál es la mejor manera para que HttpClient en las clases de servicio siga siendo una sola instancia en toda la aplicación (una instancia por punto final), pero permita que se aplique un HttpMessageHandler diferente durante las pruebas unitarias?

Un enfoque en el que he pensado sería no usar un campo estático para mantener el HttpClient en las clases de servicio, sino permitir que se inyecte a través de la inyección del constructor usando un ciclo de vida único, lo que me permitiría especificar un HttpClient con el HttpMessageHandler deseado durante las pruebas unitarias, la otra opción en la que pensé sería usar una clase de fábrica HttpClient que creara una instancia de HttpClient s en campos estáticos que luego podrían recuperarse inyectando la fábrica HttpClient en las clases de servicio, lo que nuevamente permite una implementación diferente con el HttpMessageHandler relevante para ser devuelto en pruebas unitarias. Sin embargo, ninguno de los anteriores se siente particularmente limpio y parece que debe haber una mejor manera.

Cualquier pregunta, hágamelo saber.

about 4 years ago · Santiago Trujillo
3 Respostas
Responde à pergunta

0

Agregar a la conversación desde los comentarios parece que necesitaría una fábrica HttpClient

 public interface IHttpClientFactory { HttpClient Create(string endpoint); }

y la implementación de la funcionalidad central podría verse así.

 public class DefaultHttpClientFactory : IHttpClientFactory, IDisposable { private readonly ConcurrentDictionary<string, HttpClient> _httpClients; public DefaultHttpClientFactory() { this._httpClients = new ConcurrentDictionary<string, HttpClient>(); } public HttpClient Create(string endpoint) { if (this._httpClients.TryGetValue(endpoint, out var client)) { return client; } client = new HttpClient { BaseAddress = new Uri(endpoint), }; this._httpClients.TryAdd(endpoint, client); return client; } public void Dispose() { this.Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { foreach (var httpClient in this._httpClients) { httpClient.Value.Dispose(); } } }

Dicho esto, si no está particularmente satisfecho con el diseño anterior. Puede abstraer la dependencia de HttpClient detrás de un servicio para que el cliente no se convierta en un detalle de implementación.

Que los consumidores del servicio no necesitan saber exactamente cómo se recuperan los datos.

about 4 years ago · Santiago Trujillo Relatório

0

Piensas complicado. Todo lo que necesita es una fábrica HttpClient o un accesorio con una propiedad HttpClient y usarlo de la misma manera que ASP.NET Core permite que se inyecte HttpContext

 public interface IHttpClientAccessor { HttpClient Client { get; } } public class DefaultHttpClientAccessor : IHttpClientAccessor { public HttpClient Client { get; } public DefaultHttpClientAccessor() { Client = new HttpClient(); } }

e inyectar esto en sus servicios

 public class MyRestClient : IRestClient { private readonly HttpClient client; public MyRestClient(IHttpClientAccessor httpClientAccessor) { client = httpClientAccessor.Client; } }

registro en Startup.cs:

 services.AddSingleton<IHttpClientAccessor, DefaultHttpClientAccessor>();

Para pruebas unitarias, simplemente simule

 // Moq-esque // Arrange var httpClientAccessor = new Mock<IHttpClientAccessor>(); var httpHandler = new HttpMessageHandler(..) { ... }; var httpContext = new HttpContext(httpHandler); httpClientAccessor.SetupGet(a => a.Client).Returns(httpContext); // Act var restClient = new MyRestClient(httpClientAccessor.Object); var result = await restClient.GetSomethingAsync(...); // Assert ...
about 4 years ago · Santiago Trujillo Relatório

0

Mi preferencia actual es derivar de HttpClient una vez por dominio de punto final de destino y convertirlo en un único mediante la inyección de dependencia en lugar de usar HttpClient directamente.

Digamos que estoy haciendo solicitudes HTTP a example.com, tendría un ExampleHttpClient que hereda de HttpClient y tiene la misma firma de constructor que HttpClient , lo que le permite pasar y burlarse de HttpMessageHandler como de costumbre.

 public class ExampleHttpClient : HttpClient { public ExampleHttpClient(HttpMessageHandler handler) : base(handler) { BaseAddress = new Uri("http://example.com"); // set default headers here: content type, authentication, etc } }

Luego configuro ExampleHttpClient como singleton en mi registro de inyección de dependencia y agrego un registro para HttpMessageHandler como transitorio, ya que se creará solo una vez por tipo de cliente http. Usando este patrón, no necesito tener múltiples registros complicados para HttpClient o fábricas inteligentes para construirlos según el nombre del host de destino.

Cualquier cosa que necesite hablar con example.com debe tener una dependencia de constructor en ExampleHttpClient y luego todos comparten la misma instancia y obtienes la agrupación de conexiones según lo diseñado.

De esta manera, también le brinda un lugar más agradable para colocar cosas como encabezados predeterminados, tipos de contenido, autorización, dirección base, etc., y ayuda a evitar que la configuración http de un servicio se filtre a otro servicio.

about 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda