Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/TestableHttpClient/HttpRequestMessageAsserter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
/// <summary>
/// This class makes it easy to create assertions on a collection of <seealso cref="HttpRequestMessage"/>s.
/// </summary>
internal class HttpRequestMessageAsserter : IHttpRequestMessagesCheck
internal sealed class HttpRequestMessageAsserter : IHttpRequestMessagesCheck
{
private readonly List<string> _expectedConditions = new();

Expand Down Expand Up @@ -56,6 +56,7 @@ private void Assert(int? expectedCount = null)
/// Asserts whether requests comply with a specific filter.
/// </summary>
/// <param name="requestFilter">The filter to filter requests with before asserting.</param>
/// <param name="expectedNumberOfRequests">The number of requests with this filter.</param>
/// <param name="condition">The name of the condition, used in the exception message.</param>
/// <returns>The <seealso cref="IHttpRequestMessagesCheck"/> for further assertions.</returns>
[AssertionMethod]
Expand Down
22 changes: 12 additions & 10 deletions src/TestableHttpClient/HttpRequestMessagesCheckExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ private static IHttpRequestMessagesCheck WithHttpVersion(this IHttpRequestMessag
/// <summary>
/// Asserts whether requests were made with a specific header name. Values are ignored.
/// </summary>
/// <remarks>This method only asserts headers on <see cref="System.Net.Http.Headers.HttpRequestHeader"/></remarks>
/// <remarks>This method only asserts headers on <see cref="System.Net.Http.Headers.HttpRequestHeaders"/></remarks>
/// <param name="check">The implementation that hold all the request messages.</param>
/// <param name="headerName">The name of the header that is expected.</param>
/// <returns>The <seealso cref="IHttpRequestMessagesCheck"/> for further assertions.</returns>
Expand All @@ -97,7 +97,7 @@ private static IHttpRequestMessagesCheck WithHttpVersion(this IHttpRequestMessag
/// <summary>
/// Asserts whether requests were made with a specific header name. Values are ignored.
/// </summary>
/// <remarks>This method only asserts headers on <see cref="System.Net.Http.Headers.HttpRequestHeader"/></remarks>
/// <remarks>This method only asserts headers on <see cref="System.Net.Http.Headers.HttpRequestHeaders"/></remarks>
/// <param name="check">The implementation that hold all the request messages.</param>
/// <param name="headerName">The name of the header that is expected.</param>
/// <param name="expectedNumberOfRequests">The expected number of requests.</param>
Expand All @@ -115,7 +115,7 @@ private static IHttpRequestMessagesCheck WithRequestHeader(this IHttpRequestMess
/// <summary>
/// Asserts whether requests were made with a specific header name and value.
/// </summary>
/// <remarks>This method only asserts headers on <see cref="System.Net.Http.Headers.HttpRequestHeader"/></remarks>
/// <remarks>This method only asserts headers on <see cref="System.Net.Http.Headers.HttpRequestHeaders"/></remarks>
/// <param name="check">The implementation that hold all the request messages.</param>
/// <param name="headerName">The name of the header that is expected.</param>
/// <param name="headerValue">The value of the expected header, supports wildcards.</param>
Expand All @@ -125,7 +125,7 @@ private static IHttpRequestMessagesCheck WithRequestHeader(this IHttpRequestMess
/// <summary>
/// Asserts whether requests were made with a specific header name and value.
/// </summary>
/// <remarks>This method only asserts headers on <see cref="System.Net.Http.Headers.HttpRequestHeader"/></remarks>
/// <remarks>This method only asserts headers on <see cref="System.Net.Http.Headers.HttpRequestHeaders"/></remarks>
/// <param name="check">The implementation that hold all the request messages.</param>
/// <param name="headerName">The name of the header that is expected.</param>
/// <param name="headerValue">The value of the expected header, supports wildcards.</param>
Expand All @@ -145,7 +145,7 @@ private static IHttpRequestMessagesCheck WithRequestHeader(this IHttpRequestMess
/// <summary>
/// Asserts whether requests were made with a specific header name. Values are ignored.
/// </summary>
/// <remarks>This method only asserts headers on <see cref="System.Net.Http.Headers.HttpContentHeader"/></remarks>
/// <remarks>This method only asserts headers on <see cref="System.Net.Http.Headers.HttpContentHeaders"/></remarks>
/// <param name="check">The implementation that hold all the request messages.</param>
/// <param name="headerName">The name of the header that is expected.</param>
/// <returns>The <seealso cref="IHttpRequestMessagesCheck"/> for further assertions.</returns>
Expand All @@ -154,7 +154,7 @@ private static IHttpRequestMessagesCheck WithRequestHeader(this IHttpRequestMess
/// <summary>
/// Asserts whether requests were made with a specific header name. Values are ignored.
/// </summary>
/// <remarks>This method only asserts headers on <see cref="System.Net.Http.Headers.HttpContentHeader"/></remarks>
/// <remarks>This method only asserts headers on <see cref="System.Net.Http.Headers.HttpContentHeaders"/></remarks>
/// <param name="check">The implementation that hold all the request messages.</param>
/// <param name="headerName">The name of the header that is expected.</param>
/// <param name="expectedNumberOfRequests">The expected number of requests.</param>
Expand All @@ -172,17 +172,17 @@ private static IHttpRequestMessagesCheck WithContentHeader(this IHttpRequestMess
/// <summary>
/// Asserts whether requests were made with a specific header name and value.
/// </summary>
/// <remarks>This method only asserts headers on <see cref="System.Net.Http.Headers.HttpContentHeader"/></remarks>
/// <remarks>This method only asserts headers on <see cref="System.Net.Http.Headers.HttpContentHeaders"/></remarks>
/// <param name="check">The implementation that hold all the request messages.</param>
/// <param name="headerName">The name of the header that is expected.</param>
/// <param name="headerValue">The value of the expected header, supports wildcards.</param>
/// <returns>The <seealso cref="IHttpRequestMessagesCheck"/> for further assertions.</returns>
public static IHttpRequestMessagesCheck WithContentHeader(this IHttpRequestMessagesCheck check, string headerName, string headerValue) => WithContentHeader(check, headerName, headerValue, (int?)null);
public static IHttpRequestMessagesCheck WithContentHeader(this IHttpRequestMessagesCheck check, string headerName, string headerValue) => WithContentHeader(check, headerName, headerValue, null);

/// <summary>
/// Asserts whether requests were made with a specific header name and value.
/// </summary>
/// <remarks>This method only asserts headers on <see cref="System.Net.Http.Headers.HttpContentHeader"/></remarks>
/// <remarks>This method only asserts headers on <see cref="System.Net.Http.Headers.HttpContentHeaders"/></remarks>
/// <param name="check">The implementation that hold all the request messages.</param>
/// <param name="headerName">The name of the header that is expected.</param>
/// <param name="headerValue">The value of the expected header, supports wildcards.</param>
Expand Down Expand Up @@ -231,7 +231,7 @@ private static IHttpRequestMessagesCheck WithHeader(this IHttpRequestMessagesChe
/// <param name="headerName">The name of the header that is expected.</param>
/// <param name="headerValue">The value of the expected header, supports wildcards.</param>
/// <returns>The <seealso cref="IHttpRequestMessagesCheck"/> for further assertions.</returns>
public static IHttpRequestMessagesCheck WithHeader(this IHttpRequestMessagesCheck check, string headerName, string headerValue) => WithHeader(check, headerName, headerValue, (int?)null);
public static IHttpRequestMessagesCheck WithHeader(this IHttpRequestMessagesCheck check, string headerName, string headerValue) => WithHeader(check, headerName, headerValue, null);

/// <summary>
/// Asserts whether requests were made with a specific header name and value.
Expand Down Expand Up @@ -293,6 +293,7 @@ private static IHttpRequestMessagesCheck WithContent(this IHttpRequestMessagesCh
/// </summary>
/// <param name="check">The implementation that hold all the request messages.</param>
/// <param name="jsonObject">The object representation of the expected request content.</param>
/// <param name="jsonSerializerOptions">The serializer options that should be used for serializing te content.</param>
/// <returns>The <seealso cref="IHttpRequestMessagesCheck"/> for further assertions.</returns>
/// <remarks>Note that on .NET Framework, the HttpClient might dispose the content after sending the request.</remarks>
public static IHttpRequestMessagesCheck WithJsonContent(this IHttpRequestMessagesCheck check, object? jsonObject, JsonSerializerOptions jsonSerializerOptions) => WithJsonContent(check, jsonObject, jsonSerializerOptions, null);
Expand All @@ -312,6 +313,7 @@ private static IHttpRequestMessagesCheck WithContent(this IHttpRequestMessagesCh
/// </summary>
/// <param name="check">The implementation that hold all the request messages.</param>
/// <param name="jsonObject">The object representation of the expected request content.</param>
/// <param name="jsonSerializerOptions">The serializer options that should be used for serializing the content.</param>
/// <param name="expectedNumberOfRequests">The expected number of requests.</param>
/// <returns>The <seealso cref="IHttpRequestMessagesCheck"/> for further assertions.</returns>
/// <remarks>Note that on .NET Framework, the HttpClient might dispose the content after sending the request.</remarks>
Expand Down
6 changes: 3 additions & 3 deletions src/TestableHttpClient/HttpResponseContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
/// <summary>
/// This class contains contextual information for generating responses.
/// </summary>
public class HttpResponseContext
public sealed class HttpResponseContext
{
internal HttpResponseContext(HttpRequestMessage httpRequestMessage, IReadOnlyCollection<HttpRequestMessage> httpRequestMessages, HttpResponseMessage httpResponseMessage, TestableHttpMessageHandlerOptions? options = null)
{
Expand All @@ -14,15 +14,15 @@ internal HttpResponseContext(HttpRequestMessage httpRequestMessage, IReadOnlyCol
}

/// <summary>
/// The request message that is send by the HttpClient.
/// The request message that is sent by the HttpClient.
/// </summary>
public HttpRequestMessage HttpRequestMessage { get; }
/// <summary>
/// The requests that were send by the HttpClient.
/// </summary>
public IReadOnlyCollection<HttpRequestMessage> HttpRequestMessages { get; }
/// <summary>
/// The response message that will be send back to the HttpClient.
/// The response message that will be sent back to the HttpClient.
/// </summary>
public HttpResponseMessage HttpResponseMessage { get; }
/// <summary>
Expand Down
2 changes: 1 addition & 1 deletion src/TestableHttpClient/Response/ConfiguredResponse.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
namespace TestableHttpClient.Response;

internal class ConfiguredResponse : IResponse
internal sealed class ConfiguredResponse : IResponse
{
private readonly IResponse innerResponse;
private readonly Action<HttpResponseMessage> configureResponse;
Expand Down
2 changes: 1 addition & 1 deletion src/TestableHttpClient/Response/DelayedResponse.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
namespace TestableHttpClient.Response;

internal class DelayedResponse : IResponse
internal sealed class DelayedResponse : IResponse
{
private readonly IResponse delayedResponse;
private readonly TimeSpan delay;
Expand Down
2 changes: 1 addition & 1 deletion src/TestableHttpClient/Response/JsonResponse.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
namespace TestableHttpClient.Response;

internal class JsonResponse : HttpResponse
internal sealed class JsonResponse : HttpResponse
{
public JsonResponse(object? content, string? contentType = null)
{
Expand Down
2 changes: 1 addition & 1 deletion src/TestableHttpClient/Response/RoutingResponse.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
using static TestableHttpClient.Responses;

namespace TestableHttpClient.Response;
internal class RoutingResponse : IResponse
internal sealed class RoutingResponse : IResponse
{
public Task ExecuteAsync(HttpResponseContext context, CancellationToken cancellationToken)
{
Expand Down
2 changes: 1 addition & 1 deletion src/TestableHttpClient/Response/SelectableResponse.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
namespace TestableHttpClient.Response;

internal class SelectableResponse : IResponse
internal sealed class SelectableResponse : IResponse
{
private readonly Func<HttpResponseContext, IResponse> selector;

Expand Down
2 changes: 1 addition & 1 deletion src/TestableHttpClient/Response/SequencedResponse.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
namespace TestableHttpClient.Response;

internal class SequencedResponse : IResponse
internal sealed class SequencedResponse : IResponse
{
private readonly List<IResponse> responses;
public SequencedResponse(IEnumerable<IResponse> responses)
Expand Down
2 changes: 1 addition & 1 deletion src/TestableHttpClient/Response/TextResponse.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
namespace TestableHttpClient.Response;

internal class TextResponse : HttpResponse
internal sealed class TextResponse : HttpResponse
{
public TextResponse(string content, Encoding? encoding = null, string? mediaType = null)
{
Expand Down
8 changes: 4 additions & 4 deletions src/TestableHttpClient/Response/TimeoutResponse.cs
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
namespace TestableHttpClient.Response;

internal class TimeoutResponse : IResponse
internal sealed class TimeoutResponse : IResponse
{
public async Task ExecuteAsync(HttpResponseContext context, CancellationToken cancellationToken)
{
var cancelationSource = cancellationToken.GetSource();

if (cancelationSource is not null)
{
#if NET8_0_OR_GREATER
await cancelationSource.CancelAsync().ConfigureAwait(true);
#else
#if NETSTANDARD
cancelationSource.Cancel(false);
await Task.FromCanceled<HttpResponseMessage>(cancellationToken).ConfigureAwait(true);
#else
await cancelationSource.CancelAsync().ConfigureAwait(true);
#endif
}

Expand Down
3 changes: 3 additions & 0 deletions src/TestableHttpClient/Responses.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,13 @@ public static class Responses
/// <param name="mediaType">The media type of the content, defaults to 'text/plain'.</param>
/// <returns>A response with specific content.</returns>
public static IResponse Text(string content, Encoding? encoding = null, string? mediaType = null) => new TextResponse(content, encoding, mediaType);

/// <summary>
/// Create a response with json content.
/// </summary>
/// <param name="content">The content to serialize.</param>
/// <param name="contentType">The content type of the response, defaults to 'application/json'.</param>
/// <param name="jsonSerializerOptions">The serializer settings to use for serializing the content.</param>
/// <returns>A response with specific content.</returns>
public static IResponse Json(object? content, string? contentType = null, JsonSerializerOptions? jsonSerializerOptions = null) => new JsonResponse(content, contentType) { JsonSerializerOptions = jsonSerializerOptions };
/// <summary>
Expand All @@ -72,6 +74,7 @@ public static class Responses
/// <param name="content">The content to serialize.</param>
/// <param name="statusCode">The status code for the response.</param>
/// <param name="contentType">The content type of the response, defaults to 'application/json'.</param>
/// <param name="jsonSerializerOptions">The serializer settings to use for serializing the content.</param>
/// <returns>A response with specific content.</returns>
public static IResponse Json(object? content, HttpStatusCode statusCode, string? contentType = null, JsonSerializerOptions? jsonSerializerOptions = null) => new JsonResponse(content, contentType) { StatusCode = statusCode, JsonSerializerOptions = jsonSerializerOptions };
/// <summary>
Expand Down
2 changes: 1 addition & 1 deletion src/TestableHttpClient/TestableHttpClient.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
<PackageReference Include="Microsoft.CodeAnalysis.PublicApiAnalyzers" Version="3.3.4" PrivateAssets="All">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Nerdbank.GitVersioning" Version="3.7.112" PrivateAssets="All" />
<PackageReference Include="Nerdbank.GitVersioning" Version="3.7.115" PrivateAssets="All" />
</ItemGroup>

<ItemGroup>
Expand Down
9 changes: 4 additions & 5 deletions src/TestableHttpClient/TestableHttpMessageHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@ protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage
{
httpRequestMessages.Enqueue(request);

HttpResponseMessage responseMessage;
responseMessage = new();
HttpResponseMessage responseMessage = new();
HttpResponseContext context = new(request, httpRequestMessages, responseMessage, Options);
await response.ExecuteAsync(context, cancellationToken).ConfigureAwait(false);

Expand All @@ -39,9 +38,9 @@ protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage
/// Configure a response that creates a <see cref="HttpResponseMessage"/> that should be returned for a request.
/// </summary>
/// <param name="response">The response that should be created.</param>
/// <remarks>By default each request will receive a new response, however this is dependent on the implementation.</remarks>
/// <remarks>By default, each request will receive a new response, however this is dependent on the implementation.</remarks>
/// <example>
/// testableHttpMessageHander.RespondWith(Responses.StatusCode(HttpStatusCode.OK));
/// testableHttpMessageHandler.RespondWith(Responses.StatusCode(HttpStatusCode.OK));
/// </example>
public void RespondWith(IResponse response)
{
Expand All @@ -53,7 +52,7 @@ public void RespondWith(IResponse response)
/// </summary>
/// Sometimes the TestableHttpMessageHandler can't be replaced with a new instance, but it can be cleared.
/// The configuration is not cleared and will be kept the same.
/// <remarks>The configuration it self (Options and the configure IResponse) will not be cleared or reset.</remarks>
/// <remarks>The configuration itself (Options and the configured IResponse) will not be cleared or reset.</remarks>
public void ClearRequests()
{
httpRequestMessages.Clear();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ public static class TestableHttpMessageHandlerExtensions
/// Create an <seealso cref="HttpClient"/> configured with the TestableHttpMessageHandler.
/// </summary>
/// <param name="handler">The TestableHttpMessageHandler to set on the client.</param>
/// <param name="httpMessageHandlers">Additional handlers to add to the client.</param>
/// <returns>An HttpClient configure with the TestableHttpMessageHandler.</returns>
/// <exception cref="ArgumentNullException">The `handler` is `null`</exception>
/// <remarks>Using this method is equivalent to `new HttClient(handler)`.</remarks>
Expand All @@ -25,7 +26,7 @@ public static HttpClient CreateClient(this TestableHttpMessageHandler handler, p
/// <exception cref="ArgumentNullException">The `handler` or `configureClient` is `null`</exception>
public static HttpClient CreateClient(this TestableHttpMessageHandler handler, Action<HttpClient> configureClient)
{
return CreateClient(handler, configureClient, Enumerable.Empty<DelegatingHandler>());
return CreateClient(handler, configureClient, []);
}

public static HttpClient CreateClient(this TestableHttpMessageHandler handler, Action<HttpClient> configureClient, IEnumerable<DelegatingHandler> httpMessageHandlers)
Expand Down
Loading
Loading