-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added some useful helper classes for testing http stuff and handling …
…embedded test resources
- Loading branch information
1 parent
84022d0
commit 2546723
Showing
17 changed files
with
397 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
56 changes: 56 additions & 0 deletions
56
templates/opinionated-solution/src/BASE_NAME.Core/Common/HttpClientBase.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
using System.Net; | ||
using System.Text.Json; | ||
using BASE_NAME.Core.Exceptions; | ||
|
||
namespace BASE_NAME.Core.Common; | ||
|
||
public abstract class HttpClientBase { | ||
private static readonly JsonSerializerOptions _serializerOptions = new(JsonSerializerDefaults.Web); | ||
|
||
protected HttpClientBase(HttpClient httpClient) { | ||
HttpClient = httpClient; | ||
} | ||
|
||
protected virtual JsonSerializerOptions SerializerOptions => _serializerOptions; | ||
|
||
protected HttpClient HttpClient { get; } | ||
|
||
protected virtual async Task EnsureSuccessStatusCodeAsync(HttpResponseMessage response, CancellationToken cancellationToken) { | ||
if(response.IsSuccessStatusCode) | ||
return; | ||
|
||
var errorMessage = await GetErrorMessageAsync(response, cancellationToken); | ||
|
||
if(response.StatusCode == HttpStatusCode.BadRequest) | ||
throw new HttpBadRequestException(errorMessage, $"400 Bad Request was returned for call to {response.RequestMessage?.RequestUri}."); | ||
|
||
if(response.StatusCode == HttpStatusCode.Unauthorized) | ||
throw new HttpUnauthorizedException(errorMessage, $"401 Unauthorized was returned for call to {response.RequestMessage?.RequestUri}."); | ||
|
||
if(response.StatusCode == HttpStatusCode.NotFound) | ||
throw new HttpNotFoundException(errorMessage, $"404 Not Found was returned for call to {response.RequestMessage?.RequestUri}."); | ||
|
||
if(response.StatusCode == HttpStatusCode.InternalServerError) | ||
throw new HttpInternalServerErrorException(errorMessage, $"500 Internal Server Error was returned for call to {response.RequestMessage?.RequestUri}."); | ||
|
||
if(response.StatusCode == HttpStatusCode.ServiceUnavailable) | ||
throw new HttpServiceUnavailableException(errorMessage, $"503 Service Unavailable was returned for call to {response.RequestMessage?.RequestUri}."); | ||
|
||
throw new HttpStatusCodeException(response.StatusCode, errorMessage, $"A non-successful status code was returned for call to {response.RequestMessage?.RequestUri}."); | ||
} | ||
|
||
protected virtual async Task<string> GetErrorMessageAsync(HttpResponseMessage response, CancellationToken cancellationToken) { | ||
try { | ||
var content = await response.Content.ReadAsStringAsync(cancellationToken); | ||
return content ?? string.Empty; | ||
} catch { | ||
return string.Empty; | ||
} | ||
} | ||
|
||
protected virtual async Task<T?> DeserializeResponseAsync<T>(HttpResponseMessage response, CancellationToken cancellationToken) { | ||
var stream = await response.Content.ReadAsStreamAsync(cancellationToken); | ||
|
||
return await JsonSerializer.DeserializeAsync<T>(stream, SerializerOptions, cancellationToken); | ||
} | ||
} |
18 changes: 18 additions & 0 deletions
18
templates/opinionated-solution/src/BASE_NAME.Core/Exceptions/HttpBadRequestException.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
using System.Net; | ||
|
||
namespace BASE_NAME.Core.Exceptions; | ||
|
||
[ExcludeFromCodeCoverage] | ||
public class HttpBadRequestException : HttpExceptionBase { | ||
public HttpBadRequestException() : base(HttpStatusCode.BadRequest, null) { | ||
} | ||
|
||
public HttpBadRequestException(string? responseMessage) : base(HttpStatusCode.BadRequest, responseMessage) { | ||
} | ||
|
||
public HttpBadRequestException(string? responseMessage, string message) : base(HttpStatusCode.BadRequest, responseMessage, message) { | ||
} | ||
|
||
public HttpBadRequestException(string? responseMessage, string message, Exception innerException) : base(HttpStatusCode.BadRequest, responseMessage, message, innerException) { | ||
} | ||
} |
26 changes: 26 additions & 0 deletions
26
templates/opinionated-solution/src/BASE_NAME.Core/Exceptions/HttpExceptionBase.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
using System.Net; | ||
|
||
[assembly: SuppressMessage("Readability", "RCS1194", Justification = "Exceptions inheriting from HttpExceptionBase needs a HttpStatusCode in their constructors.", Scope = "NamespaceAndDescendants", Target = "~N:BASE_NAME.Core.Exceptions")] | ||
|
||
namespace BASE_NAME.Core.Exceptions; | ||
|
||
[ExcludeFromCodeCoverage] | ||
public abstract class HttpExceptionBase : HttpRequestException { | ||
public new HttpStatusCode? StatusCode { get; } | ||
public string? ResponseMessage { get; } | ||
|
||
protected HttpExceptionBase(HttpStatusCode statusCode, string? responseMessage) { | ||
StatusCode = statusCode; | ||
ResponseMessage = responseMessage; | ||
} | ||
|
||
protected HttpExceptionBase(HttpStatusCode statusCode, string? responseMessage, string message) : base(message) { | ||
StatusCode = statusCode; | ||
ResponseMessage = responseMessage; | ||
} | ||
|
||
protected HttpExceptionBase(HttpStatusCode statusCode, string? responseMessage, string message, Exception innerException) : base(message, innerException) { | ||
StatusCode = statusCode; | ||
ResponseMessage = responseMessage; | ||
} | ||
} |
18 changes: 18 additions & 0 deletions
18
...es/opinionated-solution/src/BASE_NAME.Core/Exceptions/HttpInternalServerErrorException.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
using System.Net; | ||
|
||
namespace BASE_NAME.Core.Exceptions; | ||
|
||
[ExcludeFromCodeCoverage] | ||
public class HttpInternalServerErrorException : HttpExceptionBase { | ||
public HttpInternalServerErrorException() : base(HttpStatusCode.InternalServerError, null) { | ||
} | ||
|
||
public HttpInternalServerErrorException(string? responseMessage) : base(HttpStatusCode.InternalServerError, responseMessage) { | ||
} | ||
|
||
public HttpInternalServerErrorException(string? responseMessage, string message) : base(HttpStatusCode.InternalServerError, responseMessage, message) { | ||
} | ||
|
||
public HttpInternalServerErrorException(string? responseMessage, string message, Exception innerException) : base(HttpStatusCode.InternalServerError, responseMessage, message, innerException) { | ||
} | ||
} |
18 changes: 18 additions & 0 deletions
18
templates/opinionated-solution/src/BASE_NAME.Core/Exceptions/HttpNotFoundException.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
using System.Net; | ||
|
||
namespace BASE_NAME.Core.Exceptions; | ||
|
||
[ExcludeFromCodeCoverage] | ||
public class HttpNotFoundException : HttpExceptionBase { | ||
public HttpNotFoundException() : base(HttpStatusCode.NotFound, null) { | ||
} | ||
|
||
public HttpNotFoundException(string? responseMessage) : base(HttpStatusCode.NotFound, responseMessage) { | ||
} | ||
|
||
public HttpNotFoundException(string? responseMessage, string message) : base(HttpStatusCode.NotFound, responseMessage, message) { | ||
} | ||
|
||
public HttpNotFoundException(string? responseMessage, string message, Exception innerException) : base(HttpStatusCode.NotFound, responseMessage, message, innerException) { | ||
} | ||
} |
18 changes: 18 additions & 0 deletions
18
...tes/opinionated-solution/src/BASE_NAME.Core/Exceptions/HttpServiceUnavailableException.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
using System.Net; | ||
|
||
namespace BASE_NAME.Core.Exceptions; | ||
|
||
[ExcludeFromCodeCoverage] | ||
public class HttpServiceUnavailableException : HttpExceptionBase { | ||
public HttpServiceUnavailableException() : base(HttpStatusCode.ServiceUnavailable, null) { | ||
} | ||
|
||
public HttpServiceUnavailableException(string? responseMessage) : base(HttpStatusCode.ServiceUnavailable, responseMessage) { | ||
} | ||
|
||
public HttpServiceUnavailableException(string? responseMessage, string message) : base(HttpStatusCode.ServiceUnavailable, responseMessage, message) { | ||
} | ||
|
||
public HttpServiceUnavailableException(string? responseMessage, string message, Exception innerException) : base(HttpStatusCode.ServiceUnavailable, responseMessage, message, innerException) { | ||
} | ||
} |
18 changes: 18 additions & 0 deletions
18
templates/opinionated-solution/src/BASE_NAME.Core/Exceptions/HttpStatusCodeException.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
using System.Net; | ||
|
||
namespace BASE_NAME.Core.Exceptions; | ||
|
||
[ExcludeFromCodeCoverage] | ||
public class HttpStatusCodeException : HttpExceptionBase { | ||
public HttpStatusCodeException(HttpStatusCode httpStatusCode) : base(httpStatusCode, null) { | ||
} | ||
|
||
public HttpStatusCodeException(HttpStatusCode httpStatusCode, string? responseMessage) : base(httpStatusCode, responseMessage) { | ||
} | ||
|
||
public HttpStatusCodeException(HttpStatusCode httpStatusCode, string? responseMessage, string message) : base(httpStatusCode, responseMessage, message) { | ||
} | ||
|
||
public HttpStatusCodeException(HttpStatusCode httpStatusCode, string? responseMessage, string message, Exception innerException) : base(httpStatusCode, responseMessage, message, innerException) { | ||
} | ||
} |
18 changes: 18 additions & 0 deletions
18
templates/opinionated-solution/src/BASE_NAME.Core/Exceptions/HttpUnauthorizedException.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
using System.Net; | ||
|
||
namespace BASE_NAME.Core.Exceptions; | ||
|
||
[ExcludeFromCodeCoverage] | ||
public class HttpUnauthorizedException : HttpExceptionBase { | ||
public HttpUnauthorizedException() : base(HttpStatusCode.Unauthorized, null) { | ||
} | ||
|
||
public HttpUnauthorizedException(string? responseMessage) : base(HttpStatusCode.Unauthorized, responseMessage) { | ||
} | ||
|
||
public HttpUnauthorizedException(string? responseMessage, string message) : base(HttpStatusCode.Unauthorized, responseMessage, message) { | ||
} | ||
|
||
public HttpUnauthorizedException(string? responseMessage, string message, Exception innerException) : base(HttpStatusCode.Unauthorized, responseMessage, message, innerException) { | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
4 changes: 0 additions & 4 deletions
4
templates/opinionated-solution/test/BASE_NAME.TestHelpers/Class1.cs
This file was deleted.
Oops, something went wrong.
22 changes: 22 additions & 0 deletions
22
templates/opinionated-solution/test/BASE_NAME.TestHelpers/Http/FakeHttpContent.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
using System.Net; | ||
using System.Text; | ||
|
||
namespace BASE_NAME.TestHelpers.Http; | ||
|
||
public class FakeHttpContent : HttpContent { | ||
public string Content { get; set; } | ||
|
||
public FakeHttpContent(string content) { | ||
Content = content ?? throw new ArgumentNullException(nameof(content)); | ||
} | ||
|
||
protected override async Task SerializeToStreamAsync(Stream stream, TransportContext? context) { | ||
var byteArray = Encoding.UTF8.GetBytes(Content); | ||
await stream.WriteAsync(byteArray); | ||
} | ||
|
||
protected override bool TryComputeLength(out long length) { | ||
length = Encoding.UTF8.GetBytes(Content).LongLength; | ||
return true; | ||
} | ||
} |
36 changes: 36 additions & 0 deletions
36
templates/opinionated-solution/test/BASE_NAME.TestHelpers/Http/FakeHttpMessageHandler.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
namespace BASE_NAME.TestHelpers.Http; | ||
|
||
public class FakeHttpMessageHandler : HttpMessageHandler { | ||
private readonly HttpResponseMessage? _response; | ||
private readonly Func<HttpRequestMessage, CancellationToken, HttpResponseMessage>? _responseFunc; | ||
private readonly Func<HttpRequestMessage, CancellationToken, Task<HttpResponseMessage>>? _asyncResponseFunc; | ||
|
||
public FakeHttpMessageHandler(HttpResponseMessage response) { | ||
_response = response; | ||
} | ||
|
||
public FakeHttpMessageHandler(Func<HttpRequestMessage, CancellationToken, HttpResponseMessage> responseFunc) { | ||
_responseFunc = responseFunc; | ||
} | ||
|
||
public FakeHttpMessageHandler(Func<HttpRequestMessage, CancellationToken, Task<HttpResponseMessage>> asyncResponseFunc) { | ||
_asyncResponseFunc = asyncResponseFunc; | ||
} | ||
|
||
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { | ||
if(_response != null) { | ||
return _response; | ||
} | ||
|
||
if(_responseFunc != null) { | ||
return _responseFunc(request, cancellationToken); | ||
} | ||
|
||
if(_asyncResponseFunc != null) { | ||
var response = await _asyncResponseFunc(request, cancellationToken); | ||
return response; | ||
} | ||
|
||
throw new InvalidOperationException("This shouldn't be able to happen."); | ||
} | ||
} |
15 changes: 15 additions & 0 deletions
15
templates/opinionated-solution/test/BASE_NAME.TestHelpers/Http/FuncHttpMessageHandler.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
namespace BASE_NAME.TestHelpers.Http; | ||
|
||
public class FuncHttpMessageHandler : HttpMessageHandler { | ||
private readonly Func<HttpRequestMessage, CancellationToken, HttpResponseMessage> _func; | ||
|
||
public FuncHttpMessageHandler(Func<HttpRequestMessage, CancellationToken, HttpResponseMessage> func) { | ||
_func = func; | ||
} | ||
|
||
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { | ||
var responseTask = new TaskCompletionSource<HttpResponseMessage>(); | ||
responseTask.SetResult(_func(request, cancellationToken)); | ||
return responseTask.Task; | ||
} | ||
} |
41 changes: 41 additions & 0 deletions
41
templates/opinionated-solution/test/BASE_NAME.TestHelpers/Http/HttpClientActivator.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
using System.Net; | ||
using BASE_NAME.Core.Common; | ||
|
||
namespace BASE_NAME.TestHelpers.Http; | ||
|
||
public static class HttpClientActivator<T> where T : HttpClientBase { | ||
public static async Task<T> GetClientWithResourceResponseAsync(HttpStatusCode httpStatusCode, string resourceName, Func<HttpClient, T> createClient) { | ||
var responseJson = await Resources.GetStringAsync(resourceName); | ||
var dummyResponse = new HttpResponseMessage(httpStatusCode) { Content = new FakeHttpContent(responseJson) }; | ||
var client = new HttpClient(new FakeHttpMessageHandler(dummyResponse)) { | ||
BaseAddress = new Uri("http://www.example.com/") | ||
}; | ||
|
||
return createClient(client); | ||
} | ||
|
||
public static T GetClient(HttpStatusCode httpStatusCode, Func<HttpClient, T> createClient) { | ||
var dummyResponse = new HttpResponseMessage(httpStatusCode); | ||
var client = new HttpClient(new FakeHttpMessageHandler(dummyResponse)) { | ||
BaseAddress = new Uri("http://www.example.com/") | ||
}; | ||
|
||
return createClient(client); | ||
} | ||
|
||
public static T GetClient(Func<HttpRequestMessage, CancellationToken, Task<HttpResponseMessage>> responseFunc, Func<HttpClient, T> createClient) { | ||
var client = new HttpClient(new FakeHttpMessageHandler(responseFunc)) { | ||
BaseAddress = new Uri("http://www.example.com/") | ||
}; | ||
|
||
return createClient(client); | ||
} | ||
|
||
public static T GetClient(Func<HttpRequestMessage, CancellationToken, HttpResponseMessage> responseFunc, Func<HttpClient, T> createClient) { | ||
var client = new HttpClient(new FakeHttpMessageHandler(responseFunc)) { | ||
BaseAddress = new Uri("http://www.example.com/") | ||
}; | ||
|
||
return createClient(client); | ||
} | ||
} |
Oops, something went wrong.