From cfed086c58fb0408b74db3f1825aa42e9180acf5 Mon Sep 17 00:00:00 2001 From: Kevin Bost Date: Thu, 19 Feb 2026 16:17:56 -0800 Subject: [PATCH] Revises HTTP response extension methods Renames `ReturnsResponse` to `ReturnsHttpResponse` for enhanced clarity and consistency within the HTTP client mocking API, explicitly indicating an HTTP response return type. Removes the redundant `ReturnsOK` helper method, streamlining the API by encouraging direct use of `ReturnsHttpResponse` with `HttpStatusCode.OK`. Refactors associated namespaces and renames the extension file for improved organization. --- Moq.AutoMock.Tests/DescribeHttpClient.cs | 50 +++++++++---------- .../DescribeHttpMessageHandler.cs | 8 +-- ...HttpMessageHandlerExtensions.Responses.cs} | 29 ++++------- .../Http/MockHttpMessageHandlerExtensions.cs | 7 ++- 4 files changed, 41 insertions(+), 53 deletions(-) rename Moq.AutoMock/Http/{ResponseExtensions.cs => MockHttpMessageHandlerExtensions.Responses.cs} (96%) diff --git a/Moq.AutoMock.Tests/DescribeHttpClient.cs b/Moq.AutoMock.Tests/DescribeHttpClient.cs index 27f5edd..8a2079d 100644 --- a/Moq.AutoMock.Tests/DescribeHttpClient.cs +++ b/Moq.AutoMock.Tests/DescribeHttpClient.cs @@ -16,10 +16,10 @@ public async Task HttpClient_CanSetupDifferentResponsesForDifferentUrls() var mocker = new AutoMocker(); mocker.SetupHttpGet("/users") - .ReturnsResponse(HttpStatusCode.OK, """{"users": []}"""); + .ReturnsHttpResponse(HttpStatusCode.OK, """{"users": []}"""); mocker.SetupHttpGet("/products") - .ReturnsResponse(HttpStatusCode.OK, """{"products": []}"""); + .ReturnsHttpResponse(HttpStatusCode.OK, """{"products": []}"""); var service = mocker.CreateInstance(); @@ -39,8 +39,8 @@ public async Task HttpClient_CanSetupSequenceOfResponses() var mocker = new AutoMocker(); mocker.SetupHttpSequence(x => x.SendAsync(It.IsAny(), It.IsAny())) - .ReturnsResponse(HttpStatusCode.ServiceUnavailable) - .ReturnsResponse(HttpStatusCode.OK, "Success"); + .ReturnsHttpResponse(HttpStatusCode.ServiceUnavailable) + .ReturnsHttpResponse(HttpStatusCode.OK, "Success"); var service = mocker.CreateInstance(); @@ -79,7 +79,7 @@ public async Task HttpClient_CanSetupHttpGetByUrl() var mocker = new AutoMocker(); string content = """[{name: "test"}]"""; mocker.SetupHttpGet("/people") - .ReturnsResponse(HttpStatusCode.OK, content); + .ReturnsHttpResponse(HttpStatusCode.OK, content); var service = mocker.CreateInstance(); @@ -96,7 +96,7 @@ public async Task HttpClient_CanSetupHttpGetByExpression() var mocker = new AutoMocker(); string content = """[{name: "test"}]"""; mocker.SetupHttpGet(r => r.RequestUri!.AbsoluteUri.EndsWith("/people")) - .ReturnsResponse(HttpStatusCode.OK, content); + .ReturnsHttpResponse(HttpStatusCode.OK, content); var service = mocker.CreateInstance(); @@ -113,7 +113,7 @@ public async Task HttpClient_SetupHttpGetDoesNotMatchOtherVerbs() var mocker = new AutoMocker(MockBehavior.Strict); string content = """[{name: "test"}]"""; mocker.SetupHttpGet("/people") - .ReturnsResponse(HttpStatusCode.OK, content); + .ReturnsHttpResponse(HttpStatusCode.OK, content); var service = mocker.CreateInstance(); await Assert.ThrowsAsync(() => service.PostAsync("https://example.com/people", "data")); @@ -125,7 +125,7 @@ public async Task HttpClient_CanSetupHttpGetErrorResponses() var mocker = new AutoMocker(); mocker.SetupHttpGet() - .ReturnsResponse(HttpStatusCode.InternalServerError, "Server Error"); + .ReturnsHttpResponse(HttpStatusCode.InternalServerError, "Server Error"); var service = mocker.CreateInstance(); @@ -158,7 +158,7 @@ public async Task HttpClient_CanSetupHttpGetResponseWithCustomHeaders() var mocker = new AutoMocker(); mocker.SetupHttpGet() - .ReturnsResponse(HttpStatusCode.OK, "Response with headers", configure: response => + .ReturnsHttpResponse(HttpStatusCode.OK, "Response with headers", configure: response => { response.Headers.Add("X-Custom-Header", "CustomValue"); }); @@ -178,7 +178,7 @@ public async Task HttpClient_CanSetupHttpPostByUrl() var mocker = new AutoMocker(); string content = """[{name: "test"}]"""; mocker.SetupHttpPost("/people", "data") - .ReturnsResponse(HttpStatusCode.OK, content); + .ReturnsHttpResponse(HttpStatusCode.OK, content); var service = mocker.CreateInstance(); @@ -195,7 +195,7 @@ public async Task HttpClient_CanSetupHttpPostByExpression() var mocker = new AutoMocker(); string content = """[{name: "test"}]"""; mocker.SetupHttpPost(r => r.RequestUri!.AbsoluteUri.EndsWith("/people")) - .ReturnsResponse(HttpStatusCode.OK, content); + .ReturnsHttpResponse(HttpStatusCode.OK, content); var service = mocker.CreateInstance(); @@ -212,7 +212,7 @@ public async Task HttpClient_SetupHttpPostDoesNotMatchOtherVerbs() var mocker = new AutoMocker(MockBehavior.Strict); string content = """[{name: "test"}]"""; mocker.SetupHttpPost("/people") - .ReturnsResponse(HttpStatusCode.OK, content); + .ReturnsHttpResponse(HttpStatusCode.OK, content); var service = mocker.CreateInstance(); await Assert.ThrowsAsync(() => service.GetAsync("https://example.com/people")); @@ -236,7 +236,7 @@ public async Task HttpClient_CanSetupHttpPostErrorResponses() var mocker = new AutoMocker(); mocker.SetupHttpPost() - .ReturnsResponse(HttpStatusCode.InternalServerError, "Server Error"); + .ReturnsHttpResponse(HttpStatusCode.InternalServerError, "Server Error"); var service = mocker.CreateInstance(); @@ -251,7 +251,7 @@ public async Task HttpClient_CanSetupHttpPutByUrl() var mocker = new AutoMocker(); string content = """[{name: "test"}]"""; mocker.SetupHttpPut("/people", "data") - .ReturnsResponse(HttpStatusCode.OK, content); + .ReturnsHttpResponse(HttpStatusCode.OK, content); var service = mocker.CreateInstance(); @@ -268,7 +268,7 @@ public async Task HttpClient_CanSetupHttpPutByExpression() var mocker = new AutoMocker(); string content = """[{name: "test"}]"""; mocker.SetupHttpPut(r => r.RequestUri!.AbsoluteUri.EndsWith("/people")) - .ReturnsResponse(HttpStatusCode.OK, content); + .ReturnsHttpResponse(HttpStatusCode.OK, content); var service = mocker.CreateInstance(); @@ -285,7 +285,7 @@ public async Task HttpClient_SetupHttpPutDoesNotMatchOtherVerbs() var mocker = new AutoMocker(MockBehavior.Strict); string content = """[{name: "test"}]"""; mocker.SetupHttpPut("/people") - .ReturnsResponse(HttpStatusCode.OK, content); + .ReturnsHttpResponse(HttpStatusCode.OK, content); var service = mocker.CreateInstance(); await Assert.ThrowsAsync(() => service.GetAsync("https://example.com/people")); @@ -309,7 +309,7 @@ public async Task HttpClient_CanSetupHttpPutErrorResponses() var mocker = new AutoMocker(); mocker.SetupHttpPut() - .ReturnsResponse(HttpStatusCode.InternalServerError, "Server Error"); + .ReturnsHttpResponse(HttpStatusCode.InternalServerError, "Server Error"); var service = mocker.CreateInstance(); @@ -324,7 +324,7 @@ public async Task HttpClient_CanSetupHttpDeleteByUrl() var mocker = new AutoMocker(); string content = """[{name: "test"}]"""; mocker.SetupHttpDelete("/people") - .ReturnsResponse(HttpStatusCode.OK, content); + .ReturnsHttpResponse(HttpStatusCode.OK, content); var service = mocker.CreateInstance(); @@ -341,7 +341,7 @@ public async Task HttpClient_CanSetupHttpDeleteByExpression() var mocker = new AutoMocker(); string content = """[{name: "test"}]"""; mocker.SetupHttpDelete(r => r.RequestUri!.AbsoluteUri.EndsWith("/people")) - .ReturnsResponse(HttpStatusCode.OK, content); + .ReturnsHttpResponse(HttpStatusCode.OK, content); var service = mocker.CreateInstance(); @@ -358,7 +358,7 @@ public async Task HttpClient_SetupHttpDeleteDoesNotMatchOtherVerbs() var mocker = new AutoMocker(MockBehavior.Strict); string content = """[{name: "test"}]"""; mocker.SetupHttpDelete("/people") - .ReturnsResponse(HttpStatusCode.OK, content); + .ReturnsHttpResponse(HttpStatusCode.OK, content); var service = mocker.CreateInstance(); await Assert.ThrowsAsync(() => service.GetAsync("https://example.com/people")); @@ -382,7 +382,7 @@ public async Task HttpClient_CanSetupHttpDeleteErrorResponses() var mocker = new AutoMocker(); mocker.SetupHttpDelete() - .ReturnsResponse(HttpStatusCode.InternalServerError, "Server Error"); + .ReturnsHttpResponse(HttpStatusCode.InternalServerError, "Server Error"); var service = mocker.CreateInstance(); @@ -397,7 +397,7 @@ public async Task HttpClient_CanSetupHttpHeadByUrl() var mocker = new AutoMocker(); string content = """[{name: "test"}]"""; mocker.SetupHttpHead("/people") - .ReturnsResponse(HttpStatusCode.OK, content); + .ReturnsHttpResponse(HttpStatusCode.OK, content); var service = mocker.CreateInstance(); @@ -414,7 +414,7 @@ public async Task HttpClient_CanSetupHttpHeadByExpression() var mocker = new AutoMocker(); string content = """[{name: "test"}]"""; mocker.SetupHttpHead(r => r.RequestUri!.AbsoluteUri.EndsWith("/people")) - .ReturnsResponse(HttpStatusCode.OK, content); + .ReturnsHttpResponse(HttpStatusCode.OK, content); var service = mocker.CreateInstance(); @@ -431,7 +431,7 @@ public async Task HttpClient_SetupHttpHeadDoesNotMatchOtherVerbs() var mocker = new AutoMocker(MockBehavior.Strict); string content = """[{name: "test"}]"""; mocker.SetupHttpHead("/people") - .ReturnsResponse(HttpStatusCode.OK, content); + .ReturnsHttpResponse(HttpStatusCode.OK, content); var service = mocker.CreateInstance(); await Assert.ThrowsAsync(() => service.GetAsync("https://example.com/people")); @@ -455,7 +455,7 @@ public async Task HttpClient_CanSetupHttpHeadErrorResponses() var mocker = new AutoMocker(); mocker.SetupHttpHead() - .ReturnsResponse(HttpStatusCode.InternalServerError, "Server Error"); + .ReturnsHttpResponse(HttpStatusCode.InternalServerError, "Server Error"); var service = mocker.CreateInstance(); diff --git a/Moq.AutoMock.Tests/DescribeHttpMessageHandler.cs b/Moq.AutoMock.Tests/DescribeHttpMessageHandler.cs index 1e3a33e..d447705 100644 --- a/Moq.AutoMock.Tests/DescribeHttpMessageHandler.cs +++ b/Moq.AutoMock.Tests/DescribeHttpMessageHandler.cs @@ -17,7 +17,7 @@ public async Task HttpClient_CanSetupResponses() // Setup the mock handler to return a specific response using Protected() API mocker.GetMock() .SetupHttp(x => x.SendAsync(It.IsAny(), It.IsAny())) - .ReturnsResponse(HttpStatusCode.OK, "Hello, World!"); + .ReturnsHttpResponse(HttpStatusCode.OK, "Hello, World!"); var service = mocker.CreateInstance(); @@ -45,7 +45,7 @@ public async Task HttpClient_CanVerifySpecificRequestsWereMade() mocker.GetMock() .SetupHttp(x => x.SendAsync(It.IsAny(), It.IsAny())) - .ReturnsResponse(HttpStatusCode.OK); + .ReturnsHttpResponse(HttpStatusCode.OK); var service = mocker.CreateInstance(); @@ -70,8 +70,8 @@ public async Task HttpClient_CanSetupSequenceOfResponses() mocker.GetMock() .SetupSequence(x => x.SendAsync(It.IsAny(), It.IsAny())) - .ReturnsResponse(HttpStatusCode.ServiceUnavailable) - .ReturnsResponse(HttpStatusCode.OK, "Success"); + .ReturnsHttpResponse(HttpStatusCode.ServiceUnavailable) + .ReturnsHttpResponse(HttpStatusCode.OK, "Success"); var service = mocker.CreateInstance(); diff --git a/Moq.AutoMock/Http/ResponseExtensions.cs b/Moq.AutoMock/Http/MockHttpMessageHandlerExtensions.Responses.cs similarity index 96% rename from Moq.AutoMock/Http/ResponseExtensions.cs rename to Moq.AutoMock/Http/MockHttpMessageHandlerExtensions.Responses.cs index d3ba777..c24dda9 100644 --- a/Moq.AutoMock/Http/ResponseExtensions.cs +++ b/Moq.AutoMock/Http/MockHttpMessageHandlerExtensions.Responses.cs @@ -2,10 +2,11 @@ using System.Net.Http; using System.Net.Http.Headers; using System.Text; +using Moq.AutoMock.Http; using Moq.Language; using Moq.Language.Flow; -namespace Moq.AutoMock.Http; +namespace Moq.AutoMock; /// /// Provides extension methods for configuring mocked HTTP responses in unit tests using Moq and HttpMessageHandler. @@ -41,25 +42,13 @@ private static HttpResponseMessage CreateResponse( return response; } - /// - /// Specifies the response is an HTTP OK (200). - /// - /// The setup. - /// An action to configure the response headers. - public static IReturnsResult ReturnsOK( - this ISetup> setup, - Action? configure = null) - { - return setup.ReturnsResponse(HttpStatusCode.OK, configure); - } - /// /// Specifies the response to return. /// /// The setup. /// The status code. /// An action to configure the response headers. - public static IReturnsResult ReturnsResponse( + public static IReturnsResult ReturnsHttpResponse( this ISetup> setup, HttpStatusCode statusCode, Action? configure = null) @@ -77,7 +66,7 @@ public static IReturnsResult ReturnsResponse( /// The setup. /// The status code. /// An action to configure the response headers. - public static ISetupSequentialResult> ReturnsResponse( + public static ISetupSequentialResult> ReturnsHttpResponse( this ISetupSequentialResult> setup, HttpStatusCode statusCode, Action? configure = null) @@ -95,7 +84,7 @@ public static ISetupSequentialResult> ReturnsResponse( /// The response content. /// An action to configure the response headers. /// is null. - public static IReturnsResult ReturnsResponse( + public static IReturnsResult ReturnsHttpResponse( this ISetup> setup, HttpStatusCode statusCode, HttpContent content, @@ -123,7 +112,7 @@ public static IReturnsResult ReturnsResponse( /// The response content. /// An action to configure the response headers. /// is null. - public static ISetupSequentialResult> ReturnsResponse( + public static ISetupSequentialResult> ReturnsHttpResponse( this ISetupSequentialResult> setup, HttpStatusCode statusCode, HttpContent content, @@ -150,7 +139,7 @@ public static ISetupSequentialResult> ReturnsResponse( /// The character encoding. Defaults to . /// An action to configure the response headers. /// is null. - public static IReturnsResult ReturnsResponse( + public static IReturnsResult ReturnsHttpResponse( this ISetup> setup, HttpStatusCode statusCode, string content, @@ -182,7 +171,7 @@ public static IReturnsResult ReturnsResponse( /// The character encoding. Defaults to . /// An action to configure the response headers. /// is null. - public static ISetupSequentialResult> ReturnsResponse( + public static ISetupSequentialResult> ReturnsHttpResponse( this ISetupSequentialResult> setup, HttpStatusCode statusCode, string content, @@ -210,7 +199,7 @@ public static ISetupSequentialResult> ReturnsResponse( /// The character encoding. Defaults to . /// An action to configure the response headers. /// is null. - public static IReturnsResult ReturnsResponse( + public static IReturnsResult ReturnsHttpResponse( this ISetup> setup, string content, string? mediaType = null, diff --git a/Moq.AutoMock/Http/MockHttpMessageHandlerExtensions.cs b/Moq.AutoMock/Http/MockHttpMessageHandlerExtensions.cs index d2ef4fa..b807bbf 100644 --- a/Moq.AutoMock/Http/MockHttpMessageHandlerExtensions.cs +++ b/Moq.AutoMock/Http/MockHttpMessageHandlerExtensions.cs @@ -1,15 +1,14 @@ -using System.ComponentModel; -using System.Linq.Expressions; +using System.Linq.Expressions; using System.Reflection; using Moq.Language; using Moq.Language.Flow; using Moq.Protected; -namespace Moq.AutoMock.Http; +namespace Moq.AutoMock; using System.Net.Http; +using Moq.AutoMock.Http; -[EditorBrowsable(EditorBrowsableState.Never)] public static partial class MockHttpMessageHandlerExtensions { ///