Skip to content

Commit

Permalink
WithCallback-Async (#531)
Browse files Browse the repository at this point in the history
  • Loading branch information
StefH committed Nov 4, 2020
1 parent 5b083d7 commit b8cbeb5
Show file tree
Hide file tree
Showing 5 changed files with 147 additions and 51 deletions.
25 changes: 23 additions & 2 deletions examples/WireMock.Net.Console.Net452.Classic/MainApp.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
using WireMock.Server;
using WireMock.Settings;
using WireMock.Util;
using System.Threading.Tasks;

namespace WireMock.Net.ConsoleApplication
{
Expand Down Expand Up @@ -521,9 +522,29 @@ public static void Run()
.WithBodyAsJson(new { Id = "5bdf076c-5654-4b3e-842c-7caf1fabf8c9" }));
server
.Given(Request.Create().WithPath("/random200or505").UsingGet())
.RespondWith(Response.Create().WithCallback(request => new ResponseMessage
.RespondWith(Response.Create().WithCallback(request =>
{
StatusCode = new Random().Next(1, 100) == 1 ? 504 : 200
int code = new Random().Next(1, 2) == 1 ? 505 : 200;
return new ResponseMessage
{
BodyData = new BodyData { BodyAsString = "random200or505:" + code, DetectedBodyType = Types.BodyType.String },
StatusCode = code
};
}));

server
.Given(Request.Create().WithPath("/random200or505async").UsingGet())
.RespondWith(Response.Create().WithCallback(async request =>
{
await Task.Delay(1);
int code = new Random().Next(1, 2) == 1 ? 505 : 200;
return new ResponseMessage
{
BodyData = new BodyData { BodyAsString = "random200or505async:" + code, DetectedBodyType = Types.BodyType.String },
StatusCode = code
};
}));

System.Console.WriteLine(JsonConvert.SerializeObject(server.MappingModels, Formatting.Indented));
Expand Down
44 changes: 26 additions & 18 deletions src/WireMock.Net/ResponseBuilders/ICallbackResponseBuilder.cs
Original file line number Diff line number Diff line change
@@ -1,19 +1,27 @@
using System;
using JetBrains.Annotations;
using WireMock.ResponseProviders;

namespace WireMock.ResponseBuilders
{
/// <summary>
/// The CallbackResponseBuilder interface.
/// </summary>
public interface ICallbackResponseBuilder : IResponseProvider
{
/// <summary>
/// The callback builder
/// </summary>
/// <returns>The <see cref="IResponseBuilder"/>.</returns>
[PublicAPI]
IResponseBuilder WithCallback([NotNull] Func<RequestMessage, ResponseMessage> callbackHandler);
}
using System;
using System.Threading.Tasks;
using JetBrains.Annotations;
using WireMock.ResponseProviders;

namespace WireMock.ResponseBuilders
{
/// <summary>
/// The CallbackResponseBuilder interface.
/// </summary>
public interface ICallbackResponseBuilder : IResponseProvider
{
/// <summary>
/// The callback builder
/// </summary>
/// <returns>The <see cref="IResponseBuilder"/>.</returns>
[PublicAPI]
IResponseBuilder WithCallback([NotNull] Func<RequestMessage, ResponseMessage> callbackHandler);

/// <summary>
/// The async callback builder
/// </summary>
/// <returns>The <see cref="IResponseBuilder"/>.</returns>
[PublicAPI]
IResponseBuilder WithCallback([NotNull] Func<RequestMessage, Task<ResponseMessage>> callbackHandler);
}
}
60 changes: 60 additions & 0 deletions src/WireMock.Net/ResponseBuilders/Response.WithCallback.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
using System;
using System.Threading.Tasks;
using WireMock.Validation;

namespace WireMock.ResponseBuilders
{
public partial class Response
{
/// <summary>
/// A delegate to execute to generate the response.
/// </summary>
public Func<RequestMessage, ResponseMessage> Callback { get; private set; }

/// <summary>
/// A delegate to execute to generate the response async.
/// </summary>
public Func<RequestMessage, Task<ResponseMessage>> CallbackAsync { get; private set; }

/// <summary>
/// Defines if the method WithCallback(...) is used.
/// </summary>
public bool WithCallbackUsed { get; private set; }

/// <inheritdoc cref="ICallbackResponseBuilder.WithCallback(Func{RequestMessage, ResponseMessage})"/>
public IResponseBuilder WithCallback(Func<RequestMessage, ResponseMessage> callbackHandler)
{
Check.NotNull(callbackHandler, nameof(callbackHandler));

return WithCallbackInternal(true, callbackHandler);
}

/// <inheritdoc cref="ICallbackResponseBuilder.WithCallback(Func{RequestMessage, Task{ResponseMessage}})"/>
public IResponseBuilder WithCallback(Func<RequestMessage, Task<ResponseMessage>> callbackHandler)
{
Check.NotNull(callbackHandler, nameof(callbackHandler));

return WithCallbackInternal(true, callbackHandler);
}

private IResponseBuilder WithCallbackInternal(bool withCallbackUsed, Func<RequestMessage, ResponseMessage> callbackHandler)
{
Check.NotNull(callbackHandler, nameof(callbackHandler));

WithCallbackUsed = withCallbackUsed;
Callback = callbackHandler;

return this;
}

private IResponseBuilder WithCallbackInternal(bool withCallbackUsed, Func<RequestMessage, Task<ResponseMessage>> callbackHandler)
{
Check.NotNull(callbackHandler, nameof(callbackHandler));

WithCallbackUsed = withCallbackUsed;
CallbackAsync = callbackHandler;

return this;
}
}
}
40 changes: 9 additions & 31 deletions src/WireMock.Net/ResponseBuilders/Response.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,16 +42,6 @@ public partial class Response : IResponseBuilder
/// </summary>
public ResponseMessage ResponseMessage { get; }

/// <summary>
/// A delegate to execute to generate the response.
/// </summary>
public Func<RequestMessage, ResponseMessage> Callback { get; private set; }

/// <summary>
/// Defines if the method WithCallback(...) is used.
/// </summary>
public bool WithCallbackUsed { get; private set; }

/// <summary>
/// Creates this instance.
/// </summary>
Expand Down Expand Up @@ -311,25 +301,6 @@ public IResponseBuilder WithDelay(int milliseconds)
return WithDelay(TimeSpan.FromMilliseconds(milliseconds));
}

/// <inheritdoc cref="ICallbackResponseBuilder.WithCallback"/>
public IResponseBuilder WithCallback(Func<RequestMessage, ResponseMessage> callbackHandler)
{
Check.NotNull(callbackHandler, nameof(callbackHandler));

return WithCallbackInternal(true, callbackHandler);
}

/// <inheritdoc cref="ICallbackResponseBuilder.WithCallback"/>
private IResponseBuilder WithCallbackInternal(bool withCallbackUsed, Func<RequestMessage, ResponseMessage> callbackHandler)
{
Check.NotNull(callbackHandler, nameof(callbackHandler));

WithCallbackUsed = withCallbackUsed;
Callback = callbackHandler;

return this;
}

/// <inheritdoc cref="IResponseProvider.ProvideResponseAsync(RequestMessage, IWireMockServerSettings)"/>
public async Task<ResponseMessage> ProvideResponseAsync(RequestMessage requestMessage, IWireMockServerSettings settings)
{
Expand Down Expand Up @@ -365,13 +336,20 @@ string RemoveFirstOccurrence(string source, string find)
}

ResponseMessage responseMessage;
if (Callback == null)
if (Callback == null && CallbackAsync == null)
{
responseMessage = ResponseMessage;
}
else
{
responseMessage = Callback(requestMessage);
if (Callback != null)
{
responseMessage = Callback(requestMessage);
}
else
{
responseMessage = await CallbackAsync(requestMessage);
}

if (!WithCallbackUsed)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,35 @@ public class ResponseWithCallbackTests
{
private readonly WireMockServerSettings _settings = new WireMockServerSettings();

[Fact]
public async Task Response_WithCallbackAsync()
{
// Assign
var requestMessage = new RequestMessage(new UrlDetails("http://localhost/foo"), "GET", "::1");
var response = Response.Create()
.WithCallback(async request =>
{
await Task.Delay(1);
return new ResponseMessage
{
BodyData = new BodyData
{
DetectedBodyType = BodyType.String,
BodyAsString = request.Path + "Bar"
},
StatusCode = 302
};
});

// Act
var responseMessage = await response.ProvideResponseAsync(requestMessage, _settings);

// Assert
responseMessage.BodyData.BodyAsString.Should().Be("/fooBar");
responseMessage.StatusCode.Should().Be(302);
}

[Fact]
public async Task Response_WithCallback()
{
Expand Down

0 comments on commit b8cbeb5

Please sign in to comment.