Skip to content

Commit

Permalink
Add unit tests for HttpClient with WebProxy (#1010)
Browse files Browse the repository at this point in the history
* Add test for SSL / Https

* Add unit tests for HttpClient with WebProxy

* cert.pem

* x

* skip

* example google

* revert

* host tests

* sonar
  • Loading branch information
StefH authored Oct 14, 2023
1 parent 30372a9 commit 62fa466
Show file tree
Hide file tree
Showing 8 changed files with 202 additions and 7 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using WireMock.Logging;
using WireMock.Logging;
using WireMock.Server;
using WireMock.Settings;

Expand All @@ -24,7 +24,6 @@ static void Main(string[] args)
// X509CertificateFilePath = "example.pfx",
// X509CertificatePassword = "wiremock"
}

});
System.Console.WriteLine("WireMockServer listening at {0}", string.Join(",", server.Urls));

Expand Down
2 changes: 0 additions & 2 deletions src/WireMock.Net/Owin/HostUrlOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ internal class HostUrlOptions

public int? Port { get; set; }

public int? HttpsPort { get; set; }

public HostingScheme HostingScheme { get; set; }

public IReadOnlyList<HostUrlDetails> GetDetails()
Expand Down
25 changes: 25 additions & 0 deletions src/WireMock.Net/Server/WireMockServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,31 @@ public HttpClient CreateClient(params DelegatingHandler[] handlers)
return client;
}

/// <summary>
/// Create a <see cref="HttpClient"/> which can be used to call this instance.
/// <param name="handlers">
/// <param name="innerHandler">The inner handler represents the destination of the HTTP message channel.</param>
/// 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.
/// </param>
/// </summary>
[PublicAPI]
public HttpClient CreateClient(HttpMessageHandler innerHandler, params DelegatingHandler[] handlers)
{
if (!IsStarted)
{
throw new InvalidOperationException("Unable to create HttpClient because the service is not started.");
}

var client = HttpClientFactory2.Create(innerHandler, handlers);
client.BaseAddress = new Uri(Url!);
return client;
}

/// <summary>
/// Create <see cref="HttpClient"/>s (one for each URL) which can be used to call this instance.
/// <param name="innerHandler">The inner handler represents the destination of the HTTP message channel.</param>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -215,10 +215,13 @@ public async Task HaveReceivedACall_WithHeader_ShouldCheckAllRequests()
{
// Arrange
using var server = WireMockServer.Start();
using var client = server.CreateClient();
using var client1 = server.CreateClient();

var handler = new HttpClientHandler();
using var client2 = server.CreateClient(handler);

// Act 1
await client.SendAsync(new HttpRequestMessage(HttpMethod.Get, "/")
await client1.SendAsync(new HttpRequestMessage(HttpMethod.Get, "/")
{
Headers =
{
Expand All @@ -227,7 +230,7 @@ await client.SendAsync(new HttpRequestMessage(HttpMethod.Get, "/")
});

// Act 2
await client.SendAsync(new HttpRequestMessage(HttpMethod.Get, "/")
await client2.SendAsync(new HttpRequestMessage(HttpMethod.Get, "/")
{
Headers =
{
Expand Down
60 changes: 60 additions & 0 deletions test/WireMock.Net.Tests/Owin/HostUrlOptionsTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using FluentAssertions;
using WireMock.Owin;
using WireMock.Types;
using Xunit;

namespace WireMock.Net.Tests.Owin;

[ExcludeFromCodeCoverage]
public class HostUrlOptionsTests
{
[Fact]
public void GetDetails_WithNoUrlsAndHttpScheme_ShouldReturnCorrectDetails()
{
// Arrange
var options = new HostUrlOptions
{
HostingScheme = HostingScheme.Http,
Port = 8080
};

// Act
var details = options.GetDetails();

// Assert
details.Should().HaveCount(1);
var detail = details.Single();
detail.Should().Match<HostUrlDetails>(d =>
d.Scheme == "http" &&
d.Host == "localhost" &&
d.Port == 8080 &&
d.IsHttps == false
);
}

[Fact]
public void GetDetails_WithNoUrlsAndHttpsScheme_ShouldReturnCorrectDetails()
{
// Arrange
var options = new HostUrlOptions
{
HostingScheme = HostingScheme.Https,
Port = 8081
};

// Act
var details = options.GetDetails();

// Assert
details.Should().HaveCount(1);
var detail = details.Single();
detail.Should().Match<HostUrlDetails>(d =>
d.Scheme == "https" &&
d.Host == "localhost" &&
d.Port == 8081 &&
d.IsHttps == true
);
}
}
3 changes: 3 additions & 0 deletions test/WireMock.Net.Tests/WireMock.Net.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,9 @@
<None Update="OpenApiParser\*.yml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="cert.pem">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="responsebody.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
Expand Down
94 changes: 94 additions & 0 deletions test/WireMock.Net.Tests/WireMockServerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
Expand Down Expand Up @@ -100,6 +101,99 @@ public void WireMockServer_Should_reset_mappings()
server.Stop();
}

#if NET461_OR_GREATER || NET6_0_OR_GREATER
[Fact]
public async Task WireMockServer_Should_Support_Https()
{
// Arrange
const string body = "example";
var path = $"/foo_{Guid.NewGuid()}";
var settings = new WireMockServerSettings
{
UseSSL = true
};
var server = WireMockServer.Start(settings);

server
.Given(Request.Create()
.WithPath(path)
.UsingGet()
)
.RespondWith(Response.Create()
.WithBody(body)
);

// Configure the HttpClient to trust self-signed certificates
var handler = new HttpClientHandler
{
ServerCertificateCustomValidationCallback = (_, _, _, _) => true
};
using var client = new HttpClient(handler);

// Act
var result = await client.GetStringAsync($"{server.Url}{path}").ConfigureAwait(false);

// Assert
result.Should().Be(body);

server.Stop();
}
#endif

#if NET6_0_OR_GREATER
[Fact]
public async Task WireMockServer_When_HttpClientWithWebProxyCallsHttp_Should_Work_Correct()
{
// Arrange
const string body = "example";
var settings = new WireMockServerSettings
{
HostingScheme = HostingScheme.Http
};
var server = WireMockServer.Start(settings);

// The response to an HTTP CONNECT method, which is used to establish a tunnel with a proxy, should typically be a 200 OK status code if the connection is successful.
// This indicates that a tunnel has been established successfully between the client and the server via the proxy.
server
.Given(Request.Create()
.UsingConnect()
)
.RespondWith(Response.Create()
.WithBody("Connection established")
);

server
.Given(Request.Create()
.UsingGet()
)
.RespondWith(Response.Create()
.WithBody(body)
);

var httpUrl = server.Urls.First();

// Act
string result;
var currentProxy = HttpClient.DefaultProxy;
try
{
HttpClient.DefaultProxy = new WebProxy(httpUrl, false);

result = await new HttpClient().GetStringAsync(httpUrl).ConfigureAwait(false);
}
finally
{
// Revert
HttpClient.DefaultProxy = currentProxy;
}

// Assert
result.Should().Be(body);

server.Stop();
}
#endif

[Fact]
public async Task WireMockServer_Should_respond_a_redirect_without_body()
{
Expand Down
13 changes: 13 additions & 0 deletions test/WireMock.Net.Tests/cert.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
-----BEGIN CERTIFICATE-----
MIIB9TCCAZugAwIBAgIUYH7UM/DAXzosxsT+ea2jdYvhqqMwCgYIKoZIzj0EAwIw
UDELMAkGA1UEBhMCTkwxEzARBgNVBAgMClNvbWUtU3RhdGUxFTATBgNVBAoMDFdp
cmVNb2NrLk5ldDEVMBMGA1UEAwwMV2lyZU1vY2suTmV0MB4XDTIyMDgxMTE2MjE0
NFoXDTMyMDYxOTE2MjE0NFowUDELMAkGA1UEBhMCTkwxEzARBgNVBAgMClNvbWUt
U3RhdGUxFTATBgNVBAoMDFdpcmVNb2NrLk5ldDEVMBMGA1UEAwwMV2lyZU1vY2su
TmV0MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE39VoI268uDuIeKmRzr9e9jgM
SGeuJTvTG7+cSXmeDymrVgIGXQgmqKA8TDXpJNrRhWMd/fpsnWu1JwJUjBmspaNT
MFEwHQYDVR0OBBYEFILL8V+fAtMnccWKGAdkx2Dh/v/TMB8GA1UdIwQYMBaAFILL
8V+fAtMnccWKGAdkx2Dh/v/TMA8GA1UdEwEB/wQFMAMBAf8wCgYIKoZIzj0EAwID
SAAwRQIgKDLAG8OWK6GF5HV4kmWz3kp2V3yVsNK2V9Lw3dSE+YsCIQCK1EEBvuqc
0ncZV4ETVnOY23PWFOMk1VwN2aoTi5n++Q==
-----END CERTIFICATE-----

0 comments on commit 62fa466

Please sign in to comment.