mirror of
https://github.com/AlexMacocian/SystemExtensions.git
synced 2026-07-15 14:19:29 +00:00
Change HttpClientBuilder to work on IServiceCollection
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
using FluentAssertions;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using NSubstitute;
|
||||
using NSubstitute.ExceptionExtensions;
|
||||
using Slim;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
@@ -18,7 +18,7 @@ public sealed class HttpClientBuilderTests
|
||||
private const string SomeValue = "SomeValue";
|
||||
|
||||
private readonly HttpClientBuilder<object> httpClientBuilder;
|
||||
private readonly IServiceProducer serviceProducerMock = Substitute.For<IServiceProducer>();
|
||||
private readonly IServiceCollection serviceProducerMock = Substitute.For<IServiceCollection>();
|
||||
private readonly Uri baseAddress = new("http://contoso.co");
|
||||
|
||||
public HttpClientBuilderTests()
|
||||
@@ -63,120 +63,13 @@ public sealed class HttpClientBuilderTests
|
||||
{
|
||||
var producer = this.httpClientBuilder.Build();
|
||||
|
||||
producer.Should().Be(this.serviceProducerMock);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Build_RegistersWithServiceProducer()
|
||||
{
|
||||
this.httpClientBuilder.Build();
|
||||
|
||||
this.serviceProducerMock.Received().RegisterScoped(Arg.Any<Func<Slim.IServiceProvider, IHttpClient<object>>>(), false);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Build_CreatesExpectedClient()
|
||||
{
|
||||
this.serviceProducerMock.When(u => u.RegisterScoped(Arg.Any<Func<Slim.IServiceProvider, IHttpClient<object>>>(), false))
|
||||
.Do(callInfo =>
|
||||
{
|
||||
var factory = callInfo.ArgAt<Func<Slim.IServiceProvider, IHttpClient<object>>>(0);
|
||||
var client = factory(Substitute.For<Slim.IServiceProvider>());
|
||||
client.BaseAddress.Should().BeNull();
|
||||
client.DefaultRequestHeaders.Should().BeEmpty();
|
||||
client.MaxResponseContentBufferSize.Should().Be(2147483647L);
|
||||
client.Timeout.Should().Be(TimeSpan.FromSeconds(100));
|
||||
});
|
||||
|
||||
this.httpClientBuilder.Build();
|
||||
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Build_WithBaseAddress_ReturnsClientWithBaseAddress()
|
||||
{
|
||||
this.serviceProducerMock.When(u => u.RegisterScoped(Arg.Any<Func<Slim.IServiceProvider, IHttpClient<object>>>(), false))
|
||||
.Do(callInfo =>
|
||||
{
|
||||
var factory = callInfo.ArgAt<Func<Slim.IServiceProvider, IHttpClient<object>>>(0);
|
||||
var client = factory(Substitute.For<Slim.IServiceProvider>());
|
||||
client.BaseAddress.Should().Be(this.baseAddress);
|
||||
});
|
||||
|
||||
this.httpClientBuilder.WithBaseAddress(this.baseAddress)
|
||||
.Build();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Build_WithDefaultRequestHeaders_CallsFactory()
|
||||
{
|
||||
this.serviceProducerMock.When(u => u.RegisterScoped(Arg.Any<Func<Slim.IServiceProvider, IHttpClient<object>>>(), false))
|
||||
.Do(callInfo =>
|
||||
{
|
||||
var factory = callInfo.ArgAt<Func<Slim.IServiceProvider, IHttpClient<object>>>(0);
|
||||
var client = factory(Substitute.For<Slim.IServiceProvider>());
|
||||
client.DefaultRequestHeaders.TryGetValues(SomeHeader, out var values);
|
||||
values.Should().HaveCount(1);
|
||||
values.FirstOrDefault().Should().Be(SomeValue);
|
||||
});
|
||||
|
||||
this.httpClientBuilder.WithDefaultRequestHeadersSetup((headers) =>
|
||||
{
|
||||
headers.TryAddWithoutValidation(SomeHeader, SomeValue);
|
||||
}).Build();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Build_WithMaxResponseBufferSize_ReturnsClientWithMaxResponseBufferSize()
|
||||
{
|
||||
this.serviceProducerMock.When(u => u.RegisterScoped(Arg.Any<Func<Slim.IServiceProvider, IHttpClient<object>>>(), false))
|
||||
.Do(callInfo =>
|
||||
{
|
||||
var factory = callInfo.ArgAt<Func<Slim.IServiceProvider, IHttpClient<object>>>(0);
|
||||
var client = factory(Substitute.For<Slim.IServiceProvider>());
|
||||
client.MaxResponseContentBufferSize.Should().Be(100);
|
||||
});
|
||||
|
||||
this.httpClientBuilder.WithMaxResponseBufferSize(100)
|
||||
.Build();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Build_WithTimeout_ReturnsClientWithTimeout()
|
||||
{
|
||||
this.serviceProducerMock.When(u => u.RegisterScoped(Arg.Any<Func<Slim.IServiceProvider, IHttpClient<object>>>(), false))
|
||||
.Do(callInfo =>
|
||||
{
|
||||
var factory = callInfo.ArgAt<Func<Slim.IServiceProvider, IHttpClient<object>>>(0);
|
||||
var client = factory(Substitute.For<Slim.IServiceProvider>());
|
||||
client.Timeout.Should().Be(TimeSpan.FromSeconds(5));
|
||||
});
|
||||
|
||||
this.httpClientBuilder.WithTimeout(TimeSpan.FromSeconds(5))
|
||||
.Build();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Build_WithMessageHandler_CallsMessageHandler()
|
||||
{
|
||||
var handlerMock = new HttpMessageHandlerMock();
|
||||
this.serviceProducerMock.When(u => u.RegisterScoped(Arg.Any<Func<Slim.IServiceProvider, IHttpClient<object>>>(), false))
|
||||
.Do(async callInfo =>
|
||||
{
|
||||
var factory = callInfo.ArgAt<Func<Slim.IServiceProvider, IHttpClient<object>>>(0);
|
||||
var client = factory(Substitute.For<Slim.IServiceProvider>());
|
||||
await client.GetAsync(this.baseAddress);
|
||||
handlerMock.Called.Should().BeTrue();
|
||||
});
|
||||
|
||||
this.httpClientBuilder.WithMessageHandler(sp => handlerMock)
|
||||
.Build();
|
||||
producer.Should().BeEquivalentTo(this.serviceProducerMock);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task HttpClientBuilder_RegistersClientCorrectly_IServiceProviderReturnsExpected()
|
||||
{
|
||||
var container = new ServiceManager();
|
||||
var container = new ServiceCollection();
|
||||
var messageHandler = new HttpMessageHandlerMock();
|
||||
new HttpClientBuilder<object>(container)
|
||||
.WithBaseAddress(this.baseAddress)
|
||||
@@ -186,7 +79,8 @@ public sealed class HttpClientBuilderTests
|
||||
.WithTimeout(TimeSpan.FromSeconds(5))
|
||||
.Build();
|
||||
|
||||
var client = container.GetService<IHttpClient<object>>();
|
||||
var di = container.BuildServiceProvider();
|
||||
var client = di.GetService<IHttpClient<object>>();
|
||||
await client.GetAsync("");
|
||||
|
||||
client.Should().NotBeNull();
|
||||
|
||||
+6
-5
@@ -1,4 +1,5 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Slim;
|
||||
using System.Configuration;
|
||||
@@ -157,13 +158,13 @@ public static class ServiceManagerExtensions
|
||||
/// Register a scoped <see cref="IHttpClient{TScope}"/> to be used by the DI engine.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Type of the scoped <see cref="IHttpClient{TScope}"/>.</typeparam>
|
||||
/// <param name="serviceProducer"><see cref="IServiceProducer"/>.</param>
|
||||
/// <param name="services"><see cref="IServiceCollection"/>.</param>
|
||||
/// <returns><see cref="HttpClientBuilder{T}"/> to build the http client.</returns>
|
||||
public static HttpClientBuilder<T> RegisterHttpClient<T>(this IServiceProducer serviceProducer)
|
||||
public static HttpClientBuilder<T> RegisterHttpClient<T>(this IServiceCollection services)
|
||||
{
|
||||
serviceProducer.ThrowIfNull(nameof(serviceProducer));
|
||||
services.ThrowIfNull(nameof(services));
|
||||
|
||||
return new HttpClientBuilder<T>(serviceProducer);
|
||||
return new HttpClientBuilder<T>(services);
|
||||
}
|
||||
|
||||
[Obsolete($"{nameof(RegisterHttpFactory)} is obsolete. Please use {nameof(RegisterHttpClient)} for each service that requires an instance of {nameof(IHttpClient<object>)}.")]
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Slim;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Slim;
|
||||
using System.Extensions;
|
||||
using System.Net.Http.Headers;
|
||||
|
||||
@@ -6,7 +7,7 @@ namespace System.Net.Http;
|
||||
|
||||
public sealed class HttpClientBuilder<T>
|
||||
{
|
||||
private readonly IServiceProducer serviceProducer;
|
||||
private readonly IServiceCollection services;
|
||||
|
||||
private Uri baseAddress;
|
||||
private Func<IServiceProvider, HttpMessageHandler> httpMessageHandlerFactory;
|
||||
@@ -15,11 +16,11 @@ public sealed class HttpClientBuilder<T>
|
||||
private long maxResponseBufferSize = 2147483647L; //2GB default HttpClient value [https://docs.microsoft.com/en-us/dotnet/api/system.net.http.httpclient.maxresponsecontentbuffersize?view=net-6.0]
|
||||
private TimeSpan timeout = TimeSpan.FromSeconds(100); //100 seconds default HttpClient value [https://docs.microsoft.com/en-us/dotnet/api/system.net.http.httpclient.timeout?view=net-6.0]
|
||||
|
||||
internal HttpClientBuilder(IServiceProducer serviceProducer)
|
||||
internal HttpClientBuilder(IServiceCollection services)
|
||||
{
|
||||
serviceProducer.ThrowIfNull(nameof(serviceProducer));
|
||||
services.ThrowIfNull(nameof(services));
|
||||
|
||||
this.serviceProducer = serviceProducer;
|
||||
this.services = services;
|
||||
}
|
||||
|
||||
public HttpClientBuilder<T> WithMessageHandler(Func<IServiceProvider, HttpMessageHandler> httpMessageHandlerFactory)
|
||||
@@ -64,9 +65,9 @@ public sealed class HttpClientBuilder<T>
|
||||
return this;
|
||||
}
|
||||
|
||||
public IServiceProducer Build()
|
||||
public IServiceCollection Build()
|
||||
{
|
||||
this.serviceProducer.RegisterScoped<IHttpClient<T>>(sp =>
|
||||
this.services.AddScoped<IHttpClient<T>>(sp =>
|
||||
{
|
||||
var client = this.httpMessageHandlerFactory is not null ?
|
||||
new HttpClient<T>(this.httpMessageHandlerFactory(sp), this.disposeMessageHandler) :
|
||||
@@ -79,6 +80,6 @@ public sealed class HttpClientBuilder<T>
|
||||
return client;
|
||||
});
|
||||
|
||||
return this.serviceProducer;
|
||||
return this.services;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
<PackageLicenseFile>LICENSE</PackageLicenseFile>
|
||||
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<Version>1.3.1</Version>
|
||||
<Version>1.4.0</Version>
|
||||
<Authors>Alexandru Macocian</Authors>
|
||||
<RepositoryUrl>https://github.com/AlexMacocian/SystemExtensions</RepositoryUrl>
|
||||
<Description>Extensions for the Slim Dependency Injection engine</Description>
|
||||
|
||||
Reference in New Issue
Block a user