Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #4 +/- ##
==========================================
+ Coverage 64.08% 69.24% +5.16%
==========================================
Files 26 26
Lines 1044 1099 +55
Branches 132 132
==========================================
+ Hits 669 761 +92
+ Misses 356 319 -37
Partials 19 19
🚀 New features to boost your workflow:
|
|
Thanks for a solid PR. While the changes are generally correct and well implemented, there are a couple of things that can be improved. First, the async Task<HttpResponseMessage> IHttpClientAdapter.PatchAsync<TRequest>(
string requestUri, TRequest content, CancellationToken cancellationToken)
{
Dictionary<string, string> allHeaders = MergeHeaders(_cacheOptions.DefaultHeaders, new Dictionary<string, string>());
using HttpRequestMessage request = CreateRequestWithHeaders(HttpMethod.Patch, requestUri, allHeaders);
request.Content = JsonContent.Create(content);
HttpResponseMessage response = await _httpClient.SendAsync(request, cancellationToken).ConfigureAwait(false);
// Invalidate cache only after successful HTTP request (before response handler to maintain adapter contract)
await InvalidateRelatedCacheAsync(requestUri).ConfigureAwait(false);
return response;
}
async Task<HttpResponseMessage> IHttpClientAdapter.PatchAsync<TRequest>(
string requestUri, TRequest content, IDictionary<string, string> headers, CancellationToken cancellationToken)
{
Dictionary<string, string> allHeaders = MergeHeaders(_cacheOptions.DefaultHeaders, headers);
using HttpRequestMessage request = CreateRequestWithHeaders(HttpMethod.Patch, requestUri, allHeaders);
request.Content = JsonContent.Create(content);
HttpResponseMessage response = await _httpClient.SendAsync(request, cancellationToken).ConfigureAwait(false);
// Invalidate cache only after successful HTTP request (before response handler to maintain adapter contract)
await InvalidateRelatedCacheAsync(requestUri).ConfigureAwait(false);
return response;
}
Task<TResponse> IHttpClientAdapter.PatchAsync<TRequest, TResponse>(
string requestUri, TRequest content, CancellationToken cancellationToken) =>
PatchAsync<TRequest, TResponse>(requestUri, content, cancellationToken);
Task<TResponse> IHttpClientAdapter.PatchAsync<TRequest, TResponse>(
string requestUri, TRequest content, IDictionary<string, string> headers, CancellationToken cancellationToken) =>
PatchAsync<TRequest, TResponse>(requestUri, content, headers, cancellationToken);Secondly, you could add tests for the raw [Fact]
public async Task PatchAsync_WithoutTypedResponse_ReturnsHttpResponseMessage()
{
// Similar to existing PostAsync tests but for PATCH
}
[Fact]
public async Task PatchAsync_WithHeaders_WithoutTypedResponse_ReturnsHttpResponseMessage()
{
// Similar to existing PostAsync tests but for PATCH with headers
}Once these are addressed, the PR will have complete coverage and full functionality. The implementation will be consistent with existing patterns, well-tested, and it will follow good coding practices. |
- add HttpResponseMessage overloads for PatchAsync methods of HttpClientWithCache; - enriched PatchAsync test suite; - aligned test suites between post, put, patch and delete methods
|
That's a good points! I have implemented your suggestions in my latest commit and additionally aligned test suites between POST, PUT, PATCH and DELETE methods to further improve reliability and test coverage |
|
@dterenin-the-dev awesome! I think we're good to go. Merging. |
Description
This pull request introduces support for the HTTP PATCH method in the
HttpClientAdapterandHttpClientWithCacheclasses within theReliable.HttpClientlibrary. The changes include adding new PATCH method overloads to handle typed requests and responses, rawHttpResponseMessageresponses, and optional headers. Comprehensive unit tests have been added toHttpClientAdapterTests.cs,CachedHttpClientTests.cs, andHttpClientWithCacheTests.csto verify the functionality of the PATCH methods, including request execution, response handling, header support, and cache invalidation behavior.Changes
HttpClientAdapter
PatchAsync<TRequest, TResponse>(string, TRequest, CancellationToken)to send a PATCH request with a typed request and response, usingSendWithResponseHandlerAsyncwithHttpMethod.PatchandJsonContent.Create.PatchAsync<TRequest, TResponse>(string, TRequest, IDictionary<string, string>, CancellationToken)to include custom headers.PatchAsync<TRequest>(string, TRequest, CancellationToken)to return a rawHttpResponseMessage.PatchAsync<TRequest>(string, TRequest, IDictionary<string, string>, CancellationToken)to return a rawHttpResponseMessagewith headers.HttpClientWithCache
PatchAsync<TRequest, TResponse>(string, TRequest, CancellationToken)to send a PATCH request with a typed request and response, usingCreateRequestWithHeaders(HttpMethod.Patch, ...)andSendAsync.PatchAsync<TRequest, TResponse>(Uri, TRequest, CancellationToken)as a delegate to the string-based overload.PatchAsync<TRequest, TResponse>(string, TRequest, IDictionary<string, string>, CancellationToken)to include custom headers.PatchAsync<TRequest, TResponse>(Uri, TRequest, IDictionary<string, string>, CancellationToken)as a delegate to the string-based overload with headers.PatchAsync<TRequest>(string, TRequest, CancellationToken)andPatchAsync<TRequest>(string, TRequest, IDictionary<string, string>, CancellationToken)to return rawHttpResponseMessageresponses.IHttpClientAdapter.PatchAsyncto support the new PATCH methods.InvalidateRelatedCacheAsyncafter successful requests, consistent with POST, PUT, and DELETE behavior, to invalidate related cache entries.HttpClientAdapterTests.cs
PatchAsync_WithTypedResponse_CallsResponseHandler: Verifies thatPatchAsync<TRequest, TResponse>(string, TRequest, CancellationToken)sends a PATCH request and calls the response handler with the expectedTestResponse.PatchAsync_WithHeaders_CallsResponseHandler: TestsPatchAsync<TRequest, TResponse>(string, TRequest, IDictionary<string, string>, CancellationToken)with custom headers, ensuring the response handler is called.PatchAsync_WithoutTypedResponse_ReturnsHttpResponseMessage: Confirms thatPatchAsync<TRequest>(string, TRequest, CancellationToken)returns a rawHttpResponseMessagewith status code OK.PatchAsync_WithHeaders_WithoutTypedResponse_ReturnsHttpResponseMessage: Verifies thatPatchAsync<TRequest>(string, TRequest, IDictionary<string, string>, CancellationToken)returns a rawHttpResponseMessagewith headers.MockHttpMessageHandlerand FluentAssertions.TestRequestclass to support PATCH request payloads.CachedHttpClientTests.cs
PatchAsync_WithTypedResponse_ExecutesRequestAndDoesNotCache: TestsPatchAsync<TRequest, TResponse>(string, TRequest, CancellationToken)to ensure it sends a PATCH request, returns the expectedTestResponse, and skips caching.PatchAsync_WithHeaders_ExecutesRequestAndDoesNotCache: TestsPatchAsync<TRequest, TResponse>(string, TRequest, IDictionary<string, string>, CancellationToken)with headers, verifying the request executes and skips caching.SendAsyncwithHttpMethod.Patchto simulate PATCH behavior in the genericCachedHttpClient<TestResponse>._mockCacheis not called forGetAsyncorSetAsync, as PATCH is non-cacheable.TestRequestclass to support PATCH request payloads.HttpClientWithCacheTests.cs
PatchAsync_InvalidatesRelatedCache: Verifies thatPatchAsync<object, TestResponse>(string, object, CancellationToken)executes a PATCH request, returns the expectedTestResponse, and attempts cache invalidation.PatchAsync_WithHeaders_InvalidatesRelatedCache: TestsPatchAsync<object, TestResponse>(string, object, IDictionary<string, string>, CancellationToken)with headers, ensuring the request executes and attempts cache invalidation.PatchAsync_WithoutTypedResponse_ReturnsHttpResponseMessage: Confirms thatPatchAsync(string, object, CancellationToken)returns a rawHttpResponseMessagewith status code OK.PatchAsync_WithHeaders_WithoutTypedResponse_ReturnsHttpResponseMessage: Verifies thatPatchAsync(string, object, IDictionary<string, string>, CancellationToken)returns a rawHttpResponseMessagewith headers.PatchAsync_ResponseHandlerThrows_CacheRemainsValid: Tests that a failed response handler does not invalidate the cache.PatchAsync_SuccessfulHandling_InvalidatesCache: Verifies that a successful PATCH request returns the expected response and attempts cache invalidation.PostAsynctests, usingMockHttpMessageHandler,MockResponseHandler, andMemoryCache.InvalidateCacheAsyncis a no-op (placeholder assertionAssert.True(true)).System.Net.Http.JsonforJsonContent.Createusage.Motivation
HttpClientAdapterandHttpClientWithCacheto enable partial updates, aligning with RESTful API best practices.Testing
HttpClientAdapterTests.cs,CachedHttpClientTests.cs, andHttpClientWithCacheTests.cs.HttpMessageHandler,IHttpResponseHandler,ISimpleCacheKeyGenerator) and FluentAssertions/XUnit for assertions.JsonContent.Createfor JSON serialization to ensure compatibility with .NET 6 and later.Additional Notes
InvalidateCacheAsyncimplementation inHttpClientWithCacheis a no-op (returnsTask.CompletedTask), so cache invalidation tests use placeholder assertions. A future enhancement could implement pattern-based cache invalidation.Checklist
HttpClientAdapterandHttpClientWithCache.IHttpClientAdapterinterface with PATCH method signatures.