diff --git a/src/WireMock.Net.Minimal/Http/WireMockHttpClientFactory.cs b/src/WireMock.Net.Minimal/Http/WireMockHttpClientFactory.cs new file mode 100644 index 000000000..590080e3c --- /dev/null +++ b/src/WireMock.Net.Minimal/Http/WireMockHttpClientFactory.cs @@ -0,0 +1,18 @@ +// Copyright © WireMock.Net +#if NET5_0_OR_GREATER +using System; +using System.Net.Http; +using WireMock.Server; + +namespace WireMock.Http; + +internal class WireMockHttpClientFactory(WireMockServer server, params DelegatingHandler[] handlers) : IHttpClientFactory +{ + private readonly Lazy _lazyHttpClient = new(() => server.CreateClient()); + + public HttpClient CreateClient(string name) + { + return handlers.Length > 0 ? server.CreateClient(handlers) : _lazyHttpClient.Value; + } +} +#endif \ No newline at end of file diff --git a/src/WireMock.Net.Minimal/Server/WireMockServer.cs b/src/WireMock.Net.Minimal/Server/WireMockServer.cs index 6b9184a67..b7d46738d 100644 --- a/src/WireMock.Net.Minimal/Server/WireMockServer.cs +++ b/src/WireMock.Net.Minimal/Server/WireMockServer.cs @@ -120,6 +120,32 @@ protected virtual void Dispose(bool disposing) #endregion #region HttpClient +#if NET5_0_OR_GREATER + private readonly Lazy _lazyHttpClientFactory; + + /// + /// Create a which can be used to generate a HttpClient to call this instance. + /// + /// An ordered list of System.Net.Http.DelegatingHandler instances to be invoked + /// as an System.Net.Http.HttpRequestMessage travels from the System.Net.Http.HttpClient + /// to the network and an System.Net.Http.HttpResponseMessage travels from the network + /// back to System.Net.Http.HttpClient. The handlers are invoked in a top-down fashion. + /// That is, the first entry is invoked first for an outbound request message but + /// last for an inbound response message. + /// + /// + [PublicAPI] + public IHttpClientFactory CreateHttpClientFactory(params DelegatingHandler[] handlers) + { + if (!IsStarted) + { + throw new InvalidOperationException("Unable to create IHttpClientFactory because the service is not started."); + } + + return handlers.Length > 0 ? new WireMockHttpClientFactory(this, handlers) : _lazyHttpClientFactory.Value; + } +#endif + /// /// Create a which can be used to call this instance. /// @@ -427,6 +453,10 @@ protected WireMockServer(WireMockServerSettings settings) } InitSettings(settings); + +#if NET5_0_OR_GREATER + _lazyHttpClientFactory = new Lazy(() => new WireMockHttpClientFactory(this)); +#endif } /// diff --git a/test/WireMock.Net.Tests/WireMockServer.Admin.cs b/test/WireMock.Net.Tests/WireMockServer.Admin.cs index 4a26a7bf6..f72bf3429 100644 --- a/test/WireMock.Net.Tests/WireMockServer.Admin.cs +++ b/test/WireMock.Net.Tests/WireMockServer.Admin.cs @@ -560,6 +560,30 @@ public async Task WireMockServer_Admin_DeleteMappings() Check.That(await response.Content.ReadAsStringAsync().ConfigureAwait(false)).Equals($"{{\"Status\":\"Mappings deleted. Affected GUIDs: [{guid1}, {guid2}]\"}}"); } +#if NET5_0_OR_GREATER + [Fact] + public async Task WireMockServer_CreateHttpClientFactory_And_CallEndpoint() + { + // Arrange + var server = WireMockServer.Start(); + var factory = server.CreateHttpClientFactory(); + var client = factory.CreateClient("any name"); + + // Act + await client.GetAsync($"{server.Url}/foo").ConfigureAwait(false); + + // Assert + Check.That(server.LogEntries).HasSize(1); + var requestLogged = server.LogEntries.First(); + Check.That(requestLogged.RequestMessage.Method).IsEqualTo("GET"); + Check.That(requestLogged.RequestMessage.BodyData).IsNull(); + + // Cleanup + server.Stop(); + server.Dispose(); + } +#endif + [Fact] public async Task WireMockServer_CreateClient_And_CallEndpoint() {