From 3036710f8f84c739f72e04774e555fba1a961680 Mon Sep 17 00:00:00 2001 From: Dara Oladapo Date: Sun, 17 May 2026 22:03:53 +0100 Subject: [PATCH] Replace live URL in tests with WireMock.Net local server (closes #39) Removes the hard-coded https://daraoladapo.com from all test classes. Each test class now starts a WireMockServer in its constructor and disposes it via IDisposable, making tests offline, deterministic, and capable of asserting request headers, body content, and non-200 paths. Co-Authored-By: Claude Sonnet 4.6 --- .../DeleteTest.cs | 113 ++++++++++++---- src/HttpClientServiceHelper.Tests/GetTest.cs | 111 ++++++++++++--- .../HttpClientServiceHelper.Tests.csproj | 1 + .../PatchTest.cs | 126 +++++++++++++++--- src/HttpClientServiceHelper.Tests/PostTest.cs | 126 ++++++++++++++---- src/HttpClientServiceHelper.Tests/PutTest.cs | 124 ++++++++++++++--- 6 files changed, 492 insertions(+), 109 deletions(-) diff --git a/src/HttpClientServiceHelper.Tests/DeleteTest.cs b/src/HttpClientServiceHelper.Tests/DeleteTest.cs index ab242c5..dcc340a 100644 --- a/src/HttpClientServiceHelper.Tests/DeleteTest.cs +++ b/src/HttpClientServiceHelper.Tests/DeleteTest.cs @@ -1,53 +1,118 @@ -using HttpClientServiceHelper.Models; +using HttpClientServiceHelper.Models; +using Authorization = HttpClientServiceHelper.Models.Authorization; using System; using System.Collections.Generic; +using System.Linq; +using System.Net; using System.Net.Http; -using System.Text; using System.Threading.Tasks; +using WireMock.RequestBuilders; +using WireMock.ResponseBuilders; +using WireMock.Server; using Xunit; namespace HttpClientServiceHelper.Tests { - public class DeleteTest + public class DeleteTest : IDisposable { - string Route = "https://daraoladapo.com"; - string Token = Guid.NewGuid().ToString(); - List
Headers = new List
() { new Header() { Name = "SomeHeaderName", Value = "SomeHeaderValue" } }; + private readonly WireMockServer _server; + private readonly string _route; + private readonly string _token = Guid.NewGuid().ToString(); + private readonly List
_customHeaders = new() { new Header { Name = "X-Custom", Value = "custom-value" } }; + private readonly Authorization _auth = new() { Scheme = "Basic", Parameter = "dXNlcjpwYXNz" }; + + public DeleteTest() + { + _server = WireMockServer.Start(); + _route = _server.Urls[0]; + _server.Given(Request.Create().WithPath("/").UsingAnyMethod()) + .RespondWith(Response.Create().WithStatusCode(200).WithBody("deleted")); + _server.Given(Request.Create().WithPath("/error").UsingAnyMethod()) + .RespondWith(Response.Create().WithStatusCode(404).WithBody("not found")); + } + + public void Dispose() => _server.Dispose(); [Fact] public async Task DeleteAsync() { - var DeleteResponse = await HttpClientHelper.DeleteAsync(Route); - Assert.NotNull(DeleteResponse); - Assert.IsType(DeleteResponse); + var response = await HttpClientHelper.DeleteAsync(_route); + Assert.NotNull(response); + Assert.IsType(response); + Assert.Equal(HttpStatusCode.OK, response.StatusCode); } + [Fact] - public async Task Delete_DeleteResponseAsStringAsync() + public async Task DeleteAsync_NoAuth_DoesNotSendAuthHeader() { - var DeleteResponse = await HttpClientHelper.DeleteAndGetResponseAsStringAsync(Route); - Assert.NotNull(DeleteResponse); - Assert.IsType(DeleteResponse); + await HttpClientHelper.DeleteAsync(_route); + var entry = _server.LogEntries.Last(); + Assert.False(entry.RequestMessage.Headers.ContainsKey("Authorization")); } + [Fact] - public async Task Delete_WithToken_DeleteResponseAsStringAsync() + public async Task DeleteAsync_WithToken() { - var DeleteResponse = await HttpClientHelper.DeleteAndGetResponseAsStringAsync(Route, Token); - Assert.NotNull(DeleteResponse); - Assert.IsType(DeleteResponse); + var response = await HttpClientHelper.DeleteAsync(_route, _token); + Assert.NotNull(response); + Assert.IsType(response); + Assert.Equal(HttpStatusCode.OK, response.StatusCode); } + [Fact] - public async Task DeleteAsync_WithToken() + public async Task DeleteAsync_WithToken_SendsBearerHeader() { - var DeleteResponse = await HttpClientHelper.DeleteAsync(Route, Token); - Assert.NotNull(DeleteResponse); - Assert.IsType(DeleteResponse); + await HttpClientHelper.DeleteAsync(_route, _token); + var entry = _server.LogEntries.Last(); + Assert.True(entry.RequestMessage.Headers.ContainsKey("Authorization")); + Assert.Contains($"Bearer {_token}", entry.RequestMessage.Headers["Authorization"]); } + [Fact] public async Task DeleteAsync_WithHeaders() { - var DeleteResponse = await HttpClientHelper.DeleteAsync(Route, Headers); - Assert.NotNull(DeleteResponse); - Assert.IsType(DeleteResponse); + var response = await HttpClientHelper.DeleteAsync(_route, _customHeaders); + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + var entry = _server.LogEntries.Last(); + Assert.True(entry.RequestMessage.Headers.ContainsKey("X-Custom")); + Assert.Contains("custom-value", entry.RequestMessage.Headers["X-Custom"]); + } + + [Fact] + public async Task DeleteAsync_WithAuthorizationObject_SendsSchemeAndParameter() + { + var response = await HttpClientHelper.DeleteAsync(_route, _customHeaders, _auth); + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + var entry = _server.LogEntries.Last(); + Assert.True(entry.RequestMessage.Headers.ContainsKey("Authorization")); + Assert.Contains($"Basic {_auth.Parameter}", entry.RequestMessage.Headers["Authorization"]); + } + + [Fact] + public async Task Delete_DeleteResponseAsStringAsync() + { + var response = await HttpClientHelper.DeleteAndGetResponseAsStringAsync(_route); + Assert.NotNull(response); + Assert.IsType(response); + Assert.Equal("deleted", response); + } + + [Fact] + public async Task Delete_WithToken_DeleteResponseAsStringAsync() + { + var response = await HttpClientHelper.DeleteAndGetResponseAsStringAsync(_route, _token); + Assert.NotNull(response); + Assert.IsType(response); + var entry = _server.LogEntries.Last(); + Assert.True(entry.RequestMessage.Headers.ContainsKey("Authorization")); + Assert.Contains($"Bearer {_token}", entry.RequestMessage.Headers["Authorization"]); + } + + [Fact] + public async Task DeleteAsync_NonOkResponse_Returns404() + { + var response = await HttpClientHelper.DeleteAsync($"{_route}/error"); + Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); } } } diff --git a/src/HttpClientServiceHelper.Tests/GetTest.cs b/src/HttpClientServiceHelper.Tests/GetTest.cs index 0fbacd8..f627821 100644 --- a/src/HttpClientServiceHelper.Tests/GetTest.cs +++ b/src/HttpClientServiceHelper.Tests/GetTest.cs @@ -1,43 +1,118 @@ -using HttpClientServiceHelper.Tests.Mock; +using HttpClientServiceHelper.Models; +using Authorization = HttpClientServiceHelper.Models.Authorization; using System; using System.Collections.Generic; +using System.Linq; +using System.Net; using System.Net.Http; -using System.Text; using System.Threading.Tasks; +using WireMock.RequestBuilders; +using WireMock.ResponseBuilders; +using WireMock.Server; using Xunit; + namespace HttpClientServiceHelper.Tests { - public class GetTest + public class GetTest : IDisposable { - string Route = "https://daraoladapo.com"; - string Token = Guid.NewGuid().ToString(); + private readonly WireMockServer _server; + private readonly string _route; + private readonly string _token = Guid.NewGuid().ToString(); + private readonly List
_customHeaders = new() { new Header { Name = "X-Custom", Value = "custom-value" } }; + private readonly Authorization _auth = new() { Scheme = "Basic", Parameter = "dXNlcjpwYXNz" }; + + public GetTest() + { + _server = WireMockServer.Start(); + _route = _server.Urls[0]; + _server.Given(Request.Create().WithPath("/").UsingAnyMethod()) + .RespondWith(Response.Create().WithStatusCode(200).WithBody("ok")); + _server.Given(Request.Create().WithPath("/error").UsingAnyMethod()) + .RespondWith(Response.Create().WithStatusCode(404).WithBody("not found")); + } + + public void Dispose() => _server.Dispose(); + [Fact] public async Task GetAsync() { - var GetResponse = await HttpClientHelper.GetAsync(Route); - Assert.NotNull(GetResponse); - Assert.IsType(GetResponse); + var response = await HttpClientHelper.GetAsync(_route); + Assert.NotNull(response); + Assert.IsType(response); + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + } + + [Fact] + public async Task GetAsync_NoAuth_DoesNotSendAuthHeader() + { + await HttpClientHelper.GetAsync(_route); + var entry = _server.LogEntries.Last(); + Assert.False(entry.RequestMessage.Headers.ContainsKey("Authorization")); } + + [Fact] + public async Task GetAsync_WithToken() + { + var response = await HttpClientHelper.GetAsync(_route, _token); + Assert.NotNull(response); + Assert.IsType(response); + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + } + + [Fact] + public async Task GetAsync_WithToken_SendsBearerHeader() + { + await HttpClientHelper.GetAsync(_route, _token); + var entry = _server.LogEntries.Last(); + Assert.True(entry.RequestMessage.Headers.ContainsKey("Authorization")); + Assert.Contains($"Bearer {_token}", entry.RequestMessage.Headers["Authorization"]); + } + + [Fact] + public async Task GetAsync_WithCustomHeaders_SendsHeaders() + { + var response = await HttpClientHelper.GetAsync(_route, _customHeaders); + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + var entry = _server.LogEntries.Last(); + Assert.True(entry.RequestMessage.Headers.ContainsKey("X-Custom")); + Assert.Contains("custom-value", entry.RequestMessage.Headers["X-Custom"]); + } + + [Fact] + public async Task GetAsync_WithAuthorizationObject_SendsSchemeAndParameter() + { + var response = await HttpClientHelper.GetAsync(_route, _customHeaders, _auth); + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + var entry = _server.LogEntries.Last(); + Assert.True(entry.RequestMessage.Headers.ContainsKey("Authorization")); + Assert.Contains($"Basic {_auth.Parameter}", entry.RequestMessage.Headers["Authorization"]); + } + [Fact] public async Task Get_GetResponseAsStringAsync() { - var GetResponse = await HttpClientHelper.GetAsStringAsync(Route); - Assert.NotNull(GetResponse); - Assert.IsType(GetResponse); + var response = await HttpClientHelper.GetAsStringAsync(_route); + Assert.NotNull(response); + Assert.IsType(response); + Assert.Equal("ok", response); } + [Fact] public async Task Get_WithToken_GetResponseAsStringAsync() { - var GetResponse = await HttpClientHelper.GetAsStringAsync(Route, Token); - Assert.NotNull(GetResponse); - Assert.IsType(GetResponse); + var response = await HttpClientHelper.GetAsStringAsync(_route, _token); + Assert.NotNull(response); + Assert.IsType(response); + var entry = _server.LogEntries.Last(); + Assert.True(entry.RequestMessage.Headers.ContainsKey("Authorization")); + Assert.Contains($"Bearer {_token}", entry.RequestMessage.Headers["Authorization"]); } + [Fact] - public async Task GetAsync_WithToken() + public async Task GetAsync_NonOkResponse_Returns404() { - var GetResponse = await HttpClientHelper.GetAsync(Route, Token); - Assert.NotNull(GetResponse); - Assert.IsType(GetResponse); + var response = await HttpClientHelper.GetAsync($"{_route}/error"); + Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); } } } diff --git a/src/HttpClientServiceHelper.Tests/HttpClientServiceHelper.Tests.csproj b/src/HttpClientServiceHelper.Tests/HttpClientServiceHelper.Tests.csproj index e342ac3..27dc077 100644 --- a/src/HttpClientServiceHelper.Tests/HttpClientServiceHelper.Tests.csproj +++ b/src/HttpClientServiceHelper.Tests/HttpClientServiceHelper.Tests.csproj @@ -8,6 +8,7 @@ + runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/HttpClientServiceHelper.Tests/PatchTest.cs b/src/HttpClientServiceHelper.Tests/PatchTest.cs index 620ded3..bbe4ec2 100644 --- a/src/HttpClientServiceHelper.Tests/PatchTest.cs +++ b/src/HttpClientServiceHelper.Tests/PatchTest.cs @@ -1,46 +1,128 @@ -using System; +using HttpClientServiceHelper.Models; +using Authorization = HttpClientServiceHelper.Models.Authorization; +using HttpClientServiceHelper.Tests.Mock; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; using System.Net.Http; using System.Threading.Tasks; -using HttpClientServiceHelper.Tests.Mock; +using WireMock.RequestBuilders; +using WireMock.ResponseBuilders; +using WireMock.Server; using Xunit; namespace HttpClientServiceHelper.Tests { - public class PatchTest + public class PatchTest : IDisposable { - string Route = "https://daraoladapo.com"; - string Token = Guid.NewGuid().ToString(); + private readonly WireMockServer _server; + private readonly string _route; + private readonly string _token = Guid.NewGuid().ToString(); + private readonly List
_customHeaders = new() { new Header { Name = "X-Custom", Value = "custom-value" } }; + private readonly Authorization _auth = new() { Scheme = "Basic", Parameter = "dXNlcjpwYXNz" }; + + public PatchTest() + { + _server = WireMockServer.Start(); + _route = _server.Urls[0]; + _server.Given(Request.Create().WithPath("/").UsingAnyMethod()) + .RespondWith(Response.Create().WithStatusCode(200).WithBody("patched")); + _server.Given(Request.Create().WithPath("/error").UsingAnyMethod()) + .RespondWith(Response.Create().WithStatusCode(400).WithBody("bad request")); + } + + public void Dispose() => _server.Dispose(); + [Fact] public async Task PatchAsync() { - var _Person = Person.GetPerson(); - var PatchResponse = await HttpClientHelper.PatchAsync(Route, _Person); - Assert.NotNull(PatchResponse); - Assert.IsType(PatchResponse); + var response = await HttpClientHelper.PatchAsync(_route, Person.GetPerson()); + Assert.NotNull(response); + Assert.IsType(response); + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + } + + [Fact] + public async Task PatchAsync_NoAuth_SendsNonEmptyBody() + { + await HttpClientHelper.PatchAsync(_route, Person.GetPerson()); + var entry = _server.LogEntries.Last(); + Assert.False(entry.RequestMessage.Headers.ContainsKey("Authorization")); + Assert.NotNull(entry.RequestMessage.Body); + Assert.Contains("FirstName", entry.RequestMessage.Body); + Assert.Contains("Dara", entry.RequestMessage.Body); + } + + [Fact] + public async Task PatchAsync_WithToken() + { + var response = await HttpClientHelper.PatchAsync(_route, Person.GetPerson(), _token); + Assert.NotNull(response); + Assert.IsType(response); + Assert.Equal(HttpStatusCode.OK, response.StatusCode); } + + [Fact] + public async Task PatchAsync_WithToken_SendsBearerHeaderAndBody() + { + await HttpClientHelper.PatchAsync(_route, Person.GetPerson(), _token); + var entry = _server.LogEntries.Last(); + Assert.True(entry.RequestMessage.Headers.ContainsKey("Authorization")); + Assert.Contains($"Bearer {_token}", entry.RequestMessage.Headers["Authorization"]); + Assert.NotNull(entry.RequestMessage.Body); + Assert.Contains("FirstName", entry.RequestMessage.Body); + } + + [Fact] + public async Task PatchAsync_WithCustomHeaders_SendsHeadersAndBody() + { + var response = await HttpClientHelper.PatchAsync(_route, Person.GetPerson(), _customHeaders); + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + var entry = _server.LogEntries.Last(); + Assert.True(entry.RequestMessage.Headers.ContainsKey("X-Custom")); + Assert.Contains("custom-value", entry.RequestMessage.Headers["X-Custom"]); + Assert.NotNull(entry.RequestMessage.Body); + Assert.Contains("FirstName", entry.RequestMessage.Body); + } + + [Fact] + public async Task PatchAsync_WithAuthorizationObject_SendsSchemeParameterAndBody() + { + var response = await HttpClientHelper.PatchAsync(_route, Person.GetPerson(), _customHeaders, _auth); + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + var entry = _server.LogEntries.Last(); + Assert.True(entry.RequestMessage.Headers.ContainsKey("Authorization")); + Assert.Contains($"Basic {_auth.Parameter}", entry.RequestMessage.Headers["Authorization"]); + Assert.NotNull(entry.RequestMessage.Body); + Assert.Contains("FirstName", entry.RequestMessage.Body); + } + [Fact] public async Task Patch_GetResponseAsStringAsync() { - var _Person = Person.GetPerson(); - var PatchResponse = await HttpClientHelper.PatchAndGetResponseAsStringAsync(Route, _Person); - Assert.NotNull(PatchResponse); - Assert.IsType(PatchResponse); + var response = await HttpClientHelper.PatchAndGetResponseAsStringAsync(_route, Person.GetPerson()); + Assert.NotNull(response); + Assert.IsType(response); + Assert.Equal("patched", response); } + [Fact] public async Task Patch_WithToken_GetResponseAsStringAsync() { - var _Person = Person.GetPerson(); - var PatchResponse = await HttpClientHelper.PatchAndGetResponseAsStringAsync(Route, _Person, Token); - Assert.NotNull(PatchResponse); - Assert.IsType(PatchResponse); + var response = await HttpClientHelper.PatchAndGetResponseAsStringAsync(_route, Person.GetPerson(), _token); + Assert.NotNull(response); + Assert.IsType(response); + var entry = _server.LogEntries.Last(); + Assert.True(entry.RequestMessage.Headers.ContainsKey("Authorization")); + Assert.Contains($"Bearer {_token}", entry.RequestMessage.Headers["Authorization"]); } + [Fact] - public async Task PatchAsync_WithToken() + public async Task PatchAsync_NonOkResponse_Returns400() { - var _Person = Person.GetPerson(); - var PatchResponse = await HttpClientHelper.PatchAsync(Route, _Person, Token); - Assert.NotNull(PatchResponse); - Assert.IsType(PatchResponse); + var response = await HttpClientHelper.PatchAsync($"{_route}/error", Person.GetPerson()); + Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); } } } diff --git a/src/HttpClientServiceHelper.Tests/PostTest.cs b/src/HttpClientServiceHelper.Tests/PostTest.cs index 85db1bf..532655f 100644 --- a/src/HttpClientServiceHelper.Tests/PostTest.cs +++ b/src/HttpClientServiceHelper.Tests/PostTest.cs @@ -1,48 +1,128 @@ -using HttpClientServiceHelper.Tests.Mock; +using HttpClientServiceHelper.Models; +using Authorization = HttpClientServiceHelper.Models.Authorization; +using HttpClientServiceHelper.Tests.Mock; using System; using System.Collections.Generic; -using System.Threading.Tasks; +using System.Linq; +using System.Net; using System.Net.Http; -using System.Text; +using System.Threading.Tasks; +using WireMock.RequestBuilders; +using WireMock.ResponseBuilders; +using WireMock.Server; using Xunit; namespace HttpClientServiceHelper.Tests { - public class PostTest + public class PostTest : IDisposable { - string Route = "https://daraoladapo.com"; - string Token = Guid.NewGuid().ToString(); + private readonly WireMockServer _server; + private readonly string _route; + private readonly string _token = Guid.NewGuid().ToString(); + private readonly List
_customHeaders = new() { new Header { Name = "X-Custom", Value = "custom-value" } }; + private readonly Authorization _auth = new() { Scheme = "Basic", Parameter = "dXNlcjpwYXNz" }; + + public PostTest() + { + _server = WireMockServer.Start(); + _route = _server.Urls[0]; + _server.Given(Request.Create().WithPath("/").UsingAnyMethod()) + .RespondWith(Response.Create().WithStatusCode(200).WithBody("created")); + _server.Given(Request.Create().WithPath("/error").UsingAnyMethod()) + .RespondWith(Response.Create().WithStatusCode(422).WithBody("unprocessable")); + } + + public void Dispose() => _server.Dispose(); + [Fact] public async Task PostAsync() { - var _Person = Person.GetPerson(); - var PostResponse = await HttpClientHelper.PostAsync(Route, _Person); - Assert.NotNull(PostResponse); - Assert.IsType(PostResponse); + var response = await HttpClientHelper.PostAsync(_route, Person.GetPerson()); + Assert.NotNull(response); + Assert.IsType(response); + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + } + + [Fact] + public async Task PostAsync_NoAuth_SendsNonEmptyBody() + { + await HttpClientHelper.PostAsync(_route, Person.GetPerson()); + var entry = _server.LogEntries.Last(); + Assert.False(entry.RequestMessage.Headers.ContainsKey("Authorization")); + Assert.NotNull(entry.RequestMessage.Body); + Assert.Contains("FirstName", entry.RequestMessage.Body); + Assert.Contains("Dara", entry.RequestMessage.Body); + } + + [Fact] + public async Task PostAsync_WithToken() + { + var response = await HttpClientHelper.PostAsync(_route, Person.GetPerson(), _token); + Assert.NotNull(response); + Assert.IsType(response); + Assert.Equal(HttpStatusCode.OK, response.StatusCode); } + + [Fact] + public async Task PostAsync_WithToken_SendsBearerHeaderAndBody() + { + await HttpClientHelper.PostAsync(_route, Person.GetPerson(), _token); + var entry = _server.LogEntries.Last(); + Assert.True(entry.RequestMessage.Headers.ContainsKey("Authorization")); + Assert.Contains($"Bearer {_token}", entry.RequestMessage.Headers["Authorization"]); + Assert.NotNull(entry.RequestMessage.Body); + Assert.Contains("FirstName", entry.RequestMessage.Body); + } + + [Fact] + public async Task PostAsync_WithCustomHeaders_SendsHeadersAndBody() + { + var response = await HttpClientHelper.PostAsync(_route, Person.GetPerson(), _customHeaders); + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + var entry = _server.LogEntries.Last(); + Assert.True(entry.RequestMessage.Headers.ContainsKey("X-Custom")); + Assert.Contains("custom-value", entry.RequestMessage.Headers["X-Custom"]); + Assert.NotNull(entry.RequestMessage.Body); + Assert.Contains("FirstName", entry.RequestMessage.Body); + } + + [Fact] + public async Task PostAsync_WithAuthorizationObject_SendsSchemeParameterAndBody() + { + var response = await HttpClientHelper.PostAsync(_route, Person.GetPerson(), _customHeaders, _auth); + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + var entry = _server.LogEntries.Last(); + Assert.True(entry.RequestMessage.Headers.ContainsKey("Authorization")); + Assert.Contains($"Basic {_auth.Parameter}", entry.RequestMessage.Headers["Authorization"]); + Assert.NotNull(entry.RequestMessage.Body); + Assert.Contains("FirstName", entry.RequestMessage.Body); + } + [Fact] public async Task Post_GetResponseAsStringAsync() { - var _Person = Person.GetPerson(); - var PostResponse = await HttpClientHelper.PostAndGetResponseAsStringAsync(Route, _Person); - Assert.NotNull(PostResponse); - Assert.IsType(PostResponse); + var response = await HttpClientHelper.PostAndGetResponseAsStringAsync(_route, Person.GetPerson()); + Assert.NotNull(response); + Assert.IsType(response); + Assert.Equal("created", response); } + [Fact] public async Task Post_WithToken_GetResponseAsStringAsync() { - var _Person = Person.GetPerson(); - var PostResponse = await HttpClientHelper.PostAndGetResponseAsStringAsync(Route, _Person, Token); - Assert.NotNull(PostResponse); - Assert.IsType(PostResponse); + var response = await HttpClientHelper.PostAndGetResponseAsStringAsync(_route, Person.GetPerson(), _token); + Assert.NotNull(response); + Assert.IsType(response); + var entry = _server.LogEntries.Last(); + Assert.True(entry.RequestMessage.Headers.ContainsKey("Authorization")); + Assert.Contains($"Bearer {_token}", entry.RequestMessage.Headers["Authorization"]); } + [Fact] - public async Task PostAsync_WithToken() + public async Task PostAsync_NonOkResponse_Returns422() { - var _Person = Person.GetPerson(); - var PostResponse = await HttpClientHelper.PostAsync(Route, _Person, Token); - Assert.NotNull(PostResponse); - Assert.IsType(PostResponse); + var response = await HttpClientHelper.PostAsync($"{_route}/error", Person.GetPerson()); + Assert.Equal(HttpStatusCode.UnprocessableEntity, response.StatusCode); } } } diff --git a/src/HttpClientServiceHelper.Tests/PutTest.cs b/src/HttpClientServiceHelper.Tests/PutTest.cs index 51d4c69..807d8d5 100644 --- a/src/HttpClientServiceHelper.Tests/PutTest.cs +++ b/src/HttpClientServiceHelper.Tests/PutTest.cs @@ -1,48 +1,128 @@ -using HttpClientServiceHelper.Tests.Mock; +using HttpClientServiceHelper.Models; +using Authorization = HttpClientServiceHelper.Models.Authorization; +using HttpClientServiceHelper.Tests.Mock; using System; using System.Collections.Generic; +using System.Linq; +using System.Net; using System.Net.Http; -using System.Text; using System.Threading.Tasks; +using WireMock.RequestBuilders; +using WireMock.ResponseBuilders; +using WireMock.Server; using Xunit; namespace HttpClientServiceHelper.Tests { - public class PutTest + public class PutTest : IDisposable { - string Route = "https://daraoladapo.com"; - string Token = Guid.NewGuid().ToString(); + private readonly WireMockServer _server; + private readonly string _route; + private readonly string _token = Guid.NewGuid().ToString(); + private readonly List
_customHeaders = new() { new Header { Name = "X-Custom", Value = "custom-value" } }; + private readonly Authorization _auth = new() { Scheme = "Basic", Parameter = "dXNlcjpwYXNz" }; + + public PutTest() + { + _server = WireMockServer.Start(); + _route = _server.Urls[0]; + _server.Given(Request.Create().WithPath("/").UsingAnyMethod()) + .RespondWith(Response.Create().WithStatusCode(200).WithBody("updated")); + _server.Given(Request.Create().WithPath("/error").UsingAnyMethod()) + .RespondWith(Response.Create().WithStatusCode(404).WithBody("not found")); + } + + public void Dispose() => _server.Dispose(); + [Fact] public async Task PutAsync() { - var _Person = Person.GetPerson(); - var PutResponse = await HttpClientHelper.PutAsync(Route, _Person); - Assert.NotNull(PutResponse); - Assert.IsType(PutResponse); + var response = await HttpClientHelper.PutAsync(_route, Person.GetPerson()); + Assert.NotNull(response); + Assert.IsType(response); + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + } + + [Fact] + public async Task PutAsync_NoAuth_SendsNonEmptyBody() + { + await HttpClientHelper.PutAsync(_route, Person.GetPerson()); + var entry = _server.LogEntries.Last(); + Assert.False(entry.RequestMessage.Headers.ContainsKey("Authorization")); + Assert.NotNull(entry.RequestMessage.Body); + Assert.Contains("FirstName", entry.RequestMessage.Body); + Assert.Contains("Dara", entry.RequestMessage.Body); + } + + [Fact] + public async Task PutAsync_WithToken() + { + var response = await HttpClientHelper.PutAsync(_route, Person.GetPerson(), _token); + Assert.NotNull(response); + Assert.IsType(response); + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + } + + [Fact] + public async Task PutAsync_WithToken_SendsBearerHeaderAndBody() + { + await HttpClientHelper.PutAsync(_route, Person.GetPerson(), _token); + var entry = _server.LogEntries.Last(); + Assert.True(entry.RequestMessage.Headers.ContainsKey("Authorization")); + Assert.Contains($"Bearer {_token}", entry.RequestMessage.Headers["Authorization"]); + Assert.NotNull(entry.RequestMessage.Body); + Assert.Contains("FirstName", entry.RequestMessage.Body); + } + + [Fact] + public async Task PutAsync_WithCustomHeaders_SendsHeadersAndBody() + { + var response = await HttpClientHelper.PutAsync(_route, Person.GetPerson(), _customHeaders); + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + var entry = _server.LogEntries.Last(); + Assert.True(entry.RequestMessage.Headers.ContainsKey("X-Custom")); + Assert.Contains("custom-value", entry.RequestMessage.Headers["X-Custom"]); + Assert.NotNull(entry.RequestMessage.Body); + Assert.Contains("FirstName", entry.RequestMessage.Body); } + + [Fact] + public async Task PutAsync_WithAuthorizationObject_SendsSchemeParameterAndBody() + { + var response = await HttpClientHelper.PutAsync(_route, Person.GetPerson(), _customHeaders, _auth); + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + var entry = _server.LogEntries.Last(); + Assert.True(entry.RequestMessage.Headers.ContainsKey("Authorization")); + Assert.Contains($"Basic {_auth.Parameter}", entry.RequestMessage.Headers["Authorization"]); + Assert.NotNull(entry.RequestMessage.Body); + Assert.Contains("FirstName", entry.RequestMessage.Body); + } + [Fact] public async Task Put_GetResponseAsStringAsync() { - var _Person = Person.GetPerson(); - var PutResponse = await HttpClientHelper.PutAndGetResponseAsStringAsync(Route, _Person); - Assert.NotNull(PutResponse); - Assert.IsType(PutResponse); + var response = await HttpClientHelper.PutAndGetResponseAsStringAsync(_route, Person.GetPerson()); + Assert.NotNull(response); + Assert.IsType(response); + Assert.Equal("updated", response); } + [Fact] public async Task Put_WithToken_GetResponseAsStringAsync() { - var _Person = Person.GetPerson(); - var PutResponse = await HttpClientHelper.PutAndGetResponseAsStringAsync(Route, _Person, Token); - Assert.NotNull(PutResponse); - Assert.IsType(PutResponse); + var response = await HttpClientHelper.PutAndGetResponseAsStringAsync(_route, Person.GetPerson(), _token); + Assert.NotNull(response); + Assert.IsType(response); + var entry = _server.LogEntries.Last(); + Assert.True(entry.RequestMessage.Headers.ContainsKey("Authorization")); + Assert.Contains($"Bearer {_token}", entry.RequestMessage.Headers["Authorization"]); } + [Fact] - public async Task PutAsync_WithToken() + public async Task PutAsync_NonOkResponse_Returns404() { - var _Person = Person.GetPerson(); - var PutResponse = await HttpClientHelper.PutAsync(Route, _Person, Token); - Assert.NotNull(PutResponse); - Assert.IsType(PutResponse); + var response = await HttpClientHelper.PutAsync($"{_route}/error", Person.GetPerson()); + Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); } } }