diff --git a/examples/WireMock.Net.Console.Net452.Classic/MainApp.cs b/examples/WireMock.Net.Console.Net452.Classic/MainApp.cs
index 9ea422e8..bfcce9dc 100644
--- a/examples/WireMock.Net.Console.Net452.Classic/MainApp.cs
+++ b/examples/WireMock.Net.Console.Net452.Classic/MainApp.cs
@@ -6,6 +6,7 @@ using System.Threading.Tasks;
using Newtonsoft.Json;
using WireMock.Logging;
using WireMock.Matchers;
+using WireMock.Models;
using WireMock.RequestBuilders;
using WireMock.ResponseBuilders;
using WireMock.Server;
@@ -576,6 +577,40 @@ namespace WireMock.Net.ConsoleApplication
};
}));
+ server.Given(Request.Create().WithPath(new WildcardMatcher("/multi-webhook", true)).UsingPost())
+ .WithWebhook(new[] {
+ new Webhook()
+ {
+ Request = new WebhookRequest
+ {
+ Url = "http://localhost:12345/foo1",
+ Method = "post",
+ BodyData = new BodyData
+ {
+ BodyAsString = "OK 1!", DetectedBodyType = BodyType.String
+ },
+ Delay = 1000
+ }
+ },
+ new Webhook()
+ {
+ Request = new WebhookRequest
+ {
+ Url = "http://localhost:12345/foo2",
+ Method = "post",
+ BodyData = new BodyData
+ {
+ BodyAsString = "OK 2!",
+ DetectedBodyType = BodyType.String
+ },
+ MinimumRandomDelay = 3000,
+ MaximumRandomDelay = 7000
+ }
+ }
+ })
+ .WithWebhookFireAndForget(true)
+ .RespondWith(Response.Create().WithBody("a-response"));
+
System.Console.WriteLine(JsonConvert.SerializeObject(server.MappingModels, Formatting.Indented));
System.Console.WriteLine("Press any key to stop the server");
diff --git a/examples/WireMock.Net.Console.Net472.Classic/WireMock.Net.Console.Net472.Classic.csproj b/examples/WireMock.Net.Console.Net472.Classic/WireMock.Net.Console.Net472.Classic.csproj
index 2aa610e9..5c01887b 100644
--- a/examples/WireMock.Net.Console.Net472.Classic/WireMock.Net.Console.Net472.Classic.csproj
+++ b/examples/WireMock.Net.Console.Net472.Classic/WireMock.Net.Console.Net472.Classic.csproj
@@ -342,15 +342,6 @@
..\..\packages\TinyMapper.3.0.3\lib\net40\TinyMapper.dll
-
- ..\..\packages\WireMock.Net.1.5.3\lib\net461\WireMock.Net.dll
-
-
- ..\..\packages\WireMock.Net.Abstractions.1.5.3\lib\net451\WireMock.Net.Abstractions.dll
-
-
- ..\..\packages\WireMock.Org.Abstractions.1.5.3\lib\net45\WireMock.Org.Abstractions.dll
-
..\..\packages\XPath2.1.1.3\lib\net452\XPath2.dll
@@ -388,6 +379,16 @@
+
+
+ {b6269aac-170a-4346-8b9a-579ded3d9a94}
+ WireMock.Net.Abstractions
+
+
+ {d3804228-91f4-4502-9595-39584e5a01ad}
+ WireMock.Net
+
+
diff --git a/examples/WireMock.Net.Console.Net472.Classic/packages.config b/examples/WireMock.Net.Console.Net472.Classic/packages.config
index 47984c9d..4f0f76ae 100644
--- a/examples/WireMock.Net.Console.Net472.Classic/packages.config
+++ b/examples/WireMock.Net.Console.Net472.Classic/packages.config
@@ -147,9 +147,6 @@
-
-
-
\ No newline at end of file
diff --git a/src/WireMock.Net.Abstractions/Admin/Mappings/MappingModel.cs b/src/WireMock.Net.Abstractions/Admin/Mappings/MappingModel.cs
index 693143a7..aaddafc8 100644
--- a/src/WireMock.Net.Abstractions/Admin/Mappings/MappingModel.cs
+++ b/src/WireMock.Net.Abstractions/Admin/Mappings/MappingModel.cs
@@ -74,4 +74,9 @@ public class MappingModel
/// The Webhooks.
///
public WebhookModel[]? Webhooks { get; set; }
+
+ ///
+ /// Fire and forget for webhooks.
+ ///
+ public bool? UseWebhooksFireAndForget { get; set; }
}
\ No newline at end of file
diff --git a/src/WireMock.Net.Abstractions/Admin/Mappings/WebhookModel.cs b/src/WireMock.Net.Abstractions/Admin/Mappings/WebhookModel.cs
index 01f7fb19..514c13f9 100644
--- a/src/WireMock.Net.Abstractions/Admin/Mappings/WebhookModel.cs
+++ b/src/WireMock.Net.Abstractions/Admin/Mappings/WebhookModel.cs
@@ -1,14 +1,13 @@
-namespace WireMock.Admin.Mappings
+namespace WireMock.Admin.Mappings;
+
+///
+/// The Webhook
+///
+[FluentBuilder.AutoGenerateBuilder]
+public class WebhookModel
{
///
- /// The Webhook
+ /// The Webhook Request.
///
- [FluentBuilder.AutoGenerateBuilder]
- public class WebhookModel
- {
- ///
- /// The Webhook Request.
- ///
- public WebhookRequestModel Request { get; set; }
- }
+ public WebhookRequestModel Request { get; set; } = null!;
}
\ No newline at end of file
diff --git a/src/WireMock.Net.Abstractions/Admin/Mappings/WebhookRequestModel.cs b/src/WireMock.Net.Abstractions/Admin/Mappings/WebhookRequestModel.cs
index 021f7023..43c811f0 100644
--- a/src/WireMock.Net.Abstractions/Admin/Mappings/WebhookRequestModel.cs
+++ b/src/WireMock.Net.Abstractions/Admin/Mappings/WebhookRequestModel.cs
@@ -11,12 +11,12 @@ public class WebhookRequestModel
///
/// Gets or sets the Url.
///
- public string Url { get; set; }
+ public string Url { get; set; } = null!;
///
/// The method
///
- public string Method { get; set; }
+ public string Method { get; set; } = null!;
///
/// Gets or sets the headers.
@@ -47,4 +47,19 @@ public class WebhookRequestModel
/// The ReplaceNodeOptions to use when transforming a JSON node.
///
public string? TransformerReplaceNodeOptions { get; set; }
+
+ ///
+ /// Gets or sets the delay in milliseconds.
+ ///
+ public int? Delay { get; set; }
+
+ ///
+ /// Gets or sets the minimum random delay in milliseconds.
+ ///
+ public int? MinimumRandomDelay { get; set; }
+
+ ///
+ /// Gets or sets the maximum random delay in milliseconds.
+ ///
+ public int? MaximumRandomDelay { get; set; }
}
\ No newline at end of file
diff --git a/src/WireMock.Net.Abstractions/Models/IWebhookRequest.cs b/src/WireMock.Net.Abstractions/Models/IWebhookRequest.cs
index caa6df46..c671ccd8 100644
--- a/src/WireMock.Net.Abstractions/Models/IWebhookRequest.cs
+++ b/src/WireMock.Net.Abstractions/Models/IWebhookRequest.cs
@@ -2,46 +2,60 @@ using System.Collections.Generic;
using WireMock.Types;
using WireMock.Util;
-namespace WireMock.Models
+namespace WireMock.Models;
+
+///
+/// IWebhookRequest
+///
+public interface IWebhookRequest
{
///
- /// IWebhookRequest
+ /// The Webhook Url.
///
- public interface IWebhookRequest
- {
- ///
- /// The Webhook Url.
- ///
- string Url { get; set; }
+ string Url { get; set; }
- ///
- /// The method to use.
- ///
- string Method { get; set; }
+ ///
+ /// The method to use.
+ ///
+ string Method { get; set; }
- ///
- /// The Headers to send.
- ///
- IDictionary>? Headers { get; }
+ ///
+ /// The Headers to send.
+ ///
+ IDictionary>? Headers { get; }
- ///
- /// The body to send.
- ///
- IBodyData? BodyData { get; set; }
+ ///
+ /// The body to send.
+ ///
+ IBodyData? BodyData { get; set; }
- ///
- /// Use Transformer.
- ///
- bool? UseTransformer { get; set; }
+ ///
+ /// Use Transformer.
+ ///
+ bool? UseTransformer { get; set; }
- ///
- /// The transformer type.
- ///
- TransformerType TransformerType { get; set; }
+ ///
+ /// The transformer type.
+ ///
+ TransformerType TransformerType { get; set; }
- ///
- /// The ReplaceNodeOptions to use when transforming a JSON node.
- ///
- ReplaceNodeOptions TransformerReplaceNodeOptions { get; set; }
- }
+ ///
+ /// The ReplaceNodeOptions to use when transforming a JSON node.
+ ///
+ ReplaceNodeOptions TransformerReplaceNodeOptions { get; set; }
+
+ ///
+ /// Gets or sets the delay in milliseconds.
+ ///
+ int? Delay { get; set; }
+
+ ///
+ /// Gets or sets the minimum random delay in milliseconds.
+ ///
+ int? MinimumRandomDelay { get; set; }
+
+ ///
+ /// Gets or sets the maximum random delay in milliseconds.
+ ///
+ int? MaximumRandomDelay { get; set; }
}
\ No newline at end of file
diff --git a/src/WireMock.Net/Http/WebhookSender.cs b/src/WireMock.Net/Http/WebhookSender.cs
index 20c6a949..73295844 100644
--- a/src/WireMock.Net/Http/WebhookSender.cs
+++ b/src/WireMock.Net/Http/WebhookSender.cs
@@ -1,7 +1,9 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Net.Http;
+using System.Threading;
using System.Threading.Tasks;
using Stef.Validation;
using WireMock.Models;
@@ -17,6 +19,7 @@ namespace WireMock.Http;
internal class WebhookSender
{
private const string ClientIp = "::1";
+ private static readonly ThreadLocal Random = new(() => new Random(DateTime.UtcNow.Millisecond));
private readonly WireMockServerSettings _settings;
@@ -25,20 +28,26 @@ internal class WebhookSender
_settings = Guard.NotNull(settings);
}
- public Task SendAsync(HttpClient client, IMapping mapping, IWebhookRequest request, IRequestMessage originalRequestMessage, IResponseMessage originalResponseMessage)
+ public async Task SendAsync(
+ HttpClient client,
+ IMapping mapping,
+ IWebhookRequest webhookRequest,
+ IRequestMessage originalRequestMessage,
+ IResponseMessage originalResponseMessage
+ )
{
Guard.NotNull(client);
Guard.NotNull(mapping);
- Guard.NotNull(request);
+ Guard.NotNull(webhookRequest);
Guard.NotNull(originalRequestMessage);
Guard.NotNull(originalResponseMessage);
IBodyData? bodyData;
IDictionary>? headers;
- if (request.UseTransformer == true)
+ if (webhookRequest.UseTransformer == true)
{
ITransformer responseMessageTransformer;
- switch (request.TransformerType)
+ switch (webhookRequest.TransformerType)
{
case TransformerType.Handlebars:
var factoryHandlebars = new HandlebarsContextFactory(_settings.FileSystemHandler, _settings.HandlebarsRegistrationCallback);
@@ -47,26 +56,26 @@ internal class WebhookSender
case TransformerType.Scriban:
case TransformerType.ScribanDotLiquid:
- var factoryDotLiquid = new ScribanContextFactory(_settings.FileSystemHandler, request.TransformerType);
+ var factoryDotLiquid = new ScribanContextFactory(_settings.FileSystemHandler, webhookRequest.TransformerType);
responseMessageTransformer = new Transformer(factoryDotLiquid);
break;
default:
- throw new NotImplementedException($"TransformerType '{request.TransformerType}' is not supported.");
+ throw new NotImplementedException($"TransformerType '{webhookRequest.TransformerType}' is not supported.");
}
- (bodyData, headers) = responseMessageTransformer.Transform(mapping, originalRequestMessage, originalResponseMessage, request.BodyData, request.Headers, request.TransformerReplaceNodeOptions);
+ (bodyData, headers) = responseMessageTransformer.Transform(mapping, originalRequestMessage, originalResponseMessage, webhookRequest.BodyData, webhookRequest.Headers, webhookRequest.TransformerReplaceNodeOptions);
}
else
{
- bodyData = request.BodyData;
- headers = request.Headers;
+ bodyData = webhookRequest.BodyData;
+ headers = webhookRequest.Headers;
}
// Create RequestMessage
var requestMessage = new RequestMessage(
- new UrlDetails(request.Url),
- request.Method,
+ new UrlDetails(webhookRequest.Url),
+ webhookRequest.Method,
ClientIp,
bodyData,
headers?.ToDictionary(x => x.Key, x => x.Value.ToArray())
@@ -76,9 +85,30 @@ internal class WebhookSender
};
// Create HttpRequestMessage
- var httpRequestMessage = HttpRequestMessageHelper.Create(requestMessage, request.Url);
+ var httpRequestMessage = HttpRequestMessageHelper.Create(requestMessage, webhookRequest.Url);
+
+ // Delay (if required)
+ if (TryGetDelay(webhookRequest, out var delay))
+ {
+ await Task.Delay(delay.Value).ConfigureAwait(false);
+ }
// Call the URL
- return client.SendAsync(httpRequestMessage);
+ return await client.SendAsync(httpRequestMessage).ConfigureAwait(false);
+ }
+
+ private static bool TryGetDelay(IWebhookRequest webhookRequest, [NotNullWhen(true)] out int? delay)
+ {
+ delay = webhookRequest.Delay;
+ var minimumDelay = webhookRequest.MinimumRandomDelay;
+ var maximumDelay = webhookRequest.MaximumRandomDelay;
+
+ if (minimumDelay is not null && maximumDelay is not null && maximumDelay >= minimumDelay)
+ {
+ delay = Random.Value!.Next(minimumDelay.Value, maximumDelay.Value);
+ return true;
+ }
+
+ return delay is not null;
}
}
\ No newline at end of file
diff --git a/src/WireMock.Net/IMapping.cs b/src/WireMock.Net/IMapping.cs
index b95b2ef1..3af0f136 100644
--- a/src/WireMock.Net/IMapping.cs
+++ b/src/WireMock.Net/IMapping.cs
@@ -112,6 +112,11 @@ public interface IMapping
///
IWebhook[]? Webhooks { get; }
+ ///
+ /// Use Fire and Forget for the defined webhook(s). [Optional]
+ ///
+ public bool? UseWebhooksFireAndForget { get; set; }
+
///
/// ProvideResponseAsync
///
diff --git a/src/WireMock.Net/Mapping.cs b/src/WireMock.Net/Mapping.cs
index 3c404a21..1e978ef5 100644
--- a/src/WireMock.Net/Mapping.cs
+++ b/src/WireMock.Net/Mapping.cs
@@ -63,6 +63,9 @@ public class Mapping : IMapping
///
public IWebhook[]? Webhooks { get; }
+ ///
+ public bool? UseWebhooksFireAndForget { get; set; }
+
///
public ITimeSettings? TimeSettings { get; }
@@ -82,6 +85,7 @@ public class Mapping : IMapping
/// The next state which will occur after the current mapping execution. [Optional]
/// Only when the current state is executed this number, the next state which will occur. [Optional]
/// The Webhooks. [Optional]
+ /// Use Fire and Forget for the defined webhook(s). [Optional]
/// The TimeSettings. [Optional]
public Mapping(
Guid guid,
@@ -97,6 +101,7 @@ public class Mapping : IMapping
string? nextState,
int? stateTimes,
IWebhook[]? webhooks,
+ bool? useWebhooksFireAndForget,
ITimeSettings? timeSettings)
{
Guid = guid;
@@ -112,6 +117,7 @@ public class Mapping : IMapping
NextState = nextState;
StateTimes = stateTimes;
Webhooks = webhooks;
+ UseWebhooksFireAndForget = useWebhooksFireAndForget;
TimeSettings = timeSettings;
}
diff --git a/src/WireMock.Net/Matchers/Request/RequestMessageParamMatcher.cs b/src/WireMock.Net/Matchers/Request/RequestMessageParamMatcher.cs
index e15b4323..dc4e34f8 100644
--- a/src/WireMock.Net/Matchers/Request/RequestMessageParamMatcher.cs
+++ b/src/WireMock.Net/Matchers/Request/RequestMessageParamMatcher.cs
@@ -21,7 +21,7 @@ public class RequestMessageParamMatcher : IRequestMatcher
///
/// The key
///
- public string? Key { get; }
+ public string Key { get; } = string.Empty;
///
/// Defines if the key should be matched using case-ignore.
diff --git a/src/WireMock.Net/Models/Webhook.cs b/src/WireMock.Net/Models/Webhook.cs
index 7e2fef8b..db896bcc 100644
--- a/src/WireMock.Net/Models/Webhook.cs
+++ b/src/WireMock.Net/Models/Webhook.cs
@@ -1,11 +1,10 @@
-namespace WireMock.Models
+namespace WireMock.Models;
+
+///
+/// Webhook
+///
+public class Webhook : IWebhook
{
- ///
- /// Webhook
- ///
- public class Webhook : IWebhook
- {
- ///
- public IWebhookRequest Request { get; set; }
- }
+ ///
+ public IWebhookRequest Request { get; set; } = null!;
}
\ No newline at end of file
diff --git a/src/WireMock.Net/Models/WebhookRequest.cs b/src/WireMock.Net/Models/WebhookRequest.cs
index 9dd1401c..96d49dd9 100644
--- a/src/WireMock.Net/Models/WebhookRequest.cs
+++ b/src/WireMock.Net/Models/WebhookRequest.cs
@@ -2,32 +2,40 @@ using System.Collections.Generic;
using WireMock.Types;
using WireMock.Util;
-namespace WireMock.Models
+namespace WireMock.Models;
+
+///
+/// WebhookRequest
+///
+public class WebhookRequest : IWebhookRequest
{
- ///
- /// WebhookRequest
- ///
- public class WebhookRequest : IWebhookRequest
- {
- ///
- public string Url { get; set; }
+ ///
+ public string Url { get; set; } = null!;
- ///
- public string Method { get; set; }
+ ///
+ public string Method { get; set; } = null!;
- ///
- public IDictionary>? Headers { get; set; }
+ ///
+ public IDictionary>? Headers { get; set; }
- ///
- public IBodyData? BodyData { get; set; }
+ ///
+ public IBodyData? BodyData { get; set; }
- ///
- public bool? UseTransformer { get; set; }
+ ///
+ public bool? UseTransformer { get; set; }
- ///
- public TransformerType TransformerType { get; set; }
+ ///
+ public TransformerType TransformerType { get; set; }
- ///
- public ReplaceNodeOptions TransformerReplaceNodeOptions { get; set; }
- }
+ ///
+ public ReplaceNodeOptions TransformerReplaceNodeOptions { get; set; }
+
+ ///
+ public int? Delay { get; set; }
+
+ ///
+ public int? MinimumRandomDelay { get; set; }
+
+ ///
+ public int? MaximumRandomDelay { get; set; }
}
\ No newline at end of file
diff --git a/src/WireMock.Net/Owin/WireMockMiddleware.cs b/src/WireMock.Net/Owin/WireMockMiddleware.cs
index c00dd708..e0e088bf 100644
--- a/src/WireMock.Net/Owin/WireMockMiddleware.cs
+++ b/src/WireMock.Net/Owin/WireMockMiddleware.cs
@@ -11,8 +11,8 @@ using WireMock.Serialization;
using WireMock.Types;
using WireMock.ResponseBuilders;
using WireMock.Settings;
+using System.Collections.Generic;
#if !USE_ASPNETCORE
-using Microsoft.Owin;
using IContext = Microsoft.Owin.IOwinContext;
using OwinMiddleware = Microsoft.Owin.OwinMiddleware;
using Next = Microsoft.Owin.OwinMiddleware;
@@ -161,6 +161,7 @@ namespace WireMock.Owin
_options.Logger.Error($"Providing a Response for Mapping '{result.Match?.Mapping?.Guid}' failed. HttpStatusCode set to 500. Exception: {ex}");
response = ResponseMessageBuilder.Create(ex.Message, 500);
}
+
finally
{
var log = new LogEntry
@@ -201,20 +202,46 @@ namespace WireMock.Owin
private async Task SendToWebhooksAsync(IMapping mapping, IRequestMessage request, IResponseMessage response)
{
+ var tasks = new List>();
for (int index = 0; index < mapping.Webhooks?.Length; index++)
{
var httpClientForWebhook = HttpClientBuilder.Build(mapping.Settings.WebhookSettings ?? new WebhookSettings());
var webhookSender = new WebhookSender(mapping.Settings);
+ var webhookRequest = mapping.Webhooks[index].Request;
+ var webHookIndex = index;
+ tasks.Add(async () =>
+ {
+ try
+ {
+ await webhookSender.SendAsync(httpClientForWebhook, mapping, webhookRequest, request, response).ConfigureAwait(false);
+ }
+ catch (Exception ex)
+ {
+ _options.Logger.Error($"Sending message to Webhook [{webHookIndex}] from Mapping '{mapping.Guid}' failed. Exception: {ex}");
+ }
+ });
+ }
+
+ if (mapping.UseWebhooksFireAndForget == true)
+ {
try
{
- await webhookSender.SendAsync(httpClientForWebhook, mapping, mapping.Webhooks[index].Request, request, response).ConfigureAwait(false);
+ // Do not wait
+ await Task.Run(() =>
+ {
+ Task.WhenAll(tasks.Select(async task => await task.Invoke())).ConfigureAwait(false);
+ });
}
- catch (Exception ex)
+ catch
{
- _options.Logger.Error($"Sending message to Webhook [{index}] from Mapping '{mapping.Guid}' failed. Exception: {ex}");
+ // Ignore
}
}
+ else
+ {
+ await Task.WhenAll(tasks.Select(async task => await task.Invoke())).ConfigureAwait(false);
+ }
}
private void UpdateScenarioState(IMapping mapping)
diff --git a/src/WireMock.Net/Proxy/ProxyHelper.cs b/src/WireMock.Net/Proxy/ProxyHelper.cs
index c1847355..600d628a 100644
--- a/src/WireMock.Net/Proxy/ProxyHelper.cs
+++ b/src/WireMock.Net/Proxy/ProxyHelper.cs
@@ -119,6 +119,7 @@ internal class ProxyHelper
nextState: null,
stateTimes: null,
webhooks: null,
+ useWebhooksFireAndForget: null,
timeSettings: null
);
}
diff --git a/src/WireMock.Net/Serialization/MappingConverter.cs b/src/WireMock.Net/Serialization/MappingConverter.cs
index 2f8c08d0..96dcf870 100644
--- a/src/WireMock.Net/Serialization/MappingConverter.cs
+++ b/src/WireMock.Net/Serialization/MappingConverter.cs
@@ -43,6 +43,7 @@ internal class MappingConverter
TimeSettings = TimeSettingsMapper.Map(mapping.TimeSettings),
Title = mapping.Title,
Description = mapping.Description,
+ UseWebhooksFireAndForget = mapping.UseWebhooksFireAndForget,
Priority = mapping.Priority != 0 ? mapping.Priority : null,
Scenario = mapping.Scenario,
WhenStateIs = mapping.ExecutionConditionState,
@@ -168,7 +169,7 @@ internal class MappingConverter
mappingModel.Response.BodyDestination = response.ResponseMessage.BodyDestination;
mappingModel.Response.StatusCode = response.ResponseMessage.StatusCode;
- if (response.ResponseMessage.Headers != null && response.ResponseMessage.Headers.Count > 0)
+ if (response.ResponseMessage.Headers is { Count: > 0 })
{
mappingModel.Response.Headers = MapHeaders(response.ResponseMessage.Headers);
}
diff --git a/src/WireMock.Net/Serialization/WebhookMapper.cs b/src/WireMock.Net/Serialization/WebhookMapper.cs
index ce049e2b..ba72e9b1 100644
--- a/src/WireMock.Net/Serialization/WebhookMapper.cs
+++ b/src/WireMock.Net/Serialization/WebhookMapper.cs
@@ -20,6 +20,9 @@ internal static class WebhookMapper
{
Url = model.Request.Url,
Method = model.Request.Method,
+ Delay = model.Request.Delay,
+ MinimumRandomDelay = model.Request.MinimumRandomDelay,
+ MaximumRandomDelay = model.Request.MaximumRandomDelay,
Headers = model.Request.Headers?.ToDictionary(x => x.Key, x => new WireMockList(x.Value)) ?? new Dictionary>()
}
};
@@ -27,6 +30,7 @@ internal static class WebhookMapper
if (model.Request.UseTransformer == true)
{
webhook.Request.UseTransformer = true;
+
if (!Enum.TryParse(model.Request.TransformerType, out var transformerType))
{
transformerType = TransformerType.Handlebars;
@@ -37,7 +41,6 @@ internal static class WebhookMapper
{
option = ReplaceNodeOptions.None;
}
-
webhook.Request.TransformerReplaceNodeOptions = option;
}
@@ -72,7 +75,7 @@ internal static class WebhookMapper
public static WebhookModel Map(IWebhook webhook)
{
Guard.NotNull(webhook);
-
+
var model = new WebhookModel
{
Request = new WebhookRequestModel
@@ -82,7 +85,10 @@ internal static class WebhookMapper
Headers = webhook.Request.Headers?.ToDictionary(x => x.Key, x => x.Value.ToString()),
UseTransformer = webhook.Request.UseTransformer,
TransformerType = webhook.Request.UseTransformer == true ? webhook.Request.TransformerType.ToString() : null,
- TransformerReplaceNodeOptions = webhook.Request.TransformerReplaceNodeOptions.ToString()
+ TransformerReplaceNodeOptions = webhook.Request.TransformerReplaceNodeOptions.ToString(),
+ Delay = webhook.Request.Delay,
+ MinimumRandomDelay = webhook.Request.MinimumRandomDelay,
+ MaximumRandomDelay = webhook.Request.MaximumRandomDelay,
}
};
diff --git a/src/WireMock.Net/Server/IRespondWithAProvider.cs b/src/WireMock.Net/Server/IRespondWithAProvider.cs
index 327f397b..0efa2a92 100644
--- a/src/WireMock.Net/Server/IRespondWithAProvider.cs
+++ b/src/WireMock.Net/Server/IRespondWithAProvider.cs
@@ -123,6 +123,13 @@ namespace WireMock.Server
/// The .
IRespondWithAProvider WithWebhook(params IWebhook[] webhooks);
+ ///
+ /// Support FireAndForget for any configured Webhooks
+ ///
+ ///
+ ///
+ IRespondWithAProvider WithWebhookFireAndForget(bool UseWebhooksFireAndForget);
+
///
/// Add a Webhook to call after the response has been generated.
///
diff --git a/src/WireMock.Net/Server/RespondWithAProvider.cs b/src/WireMock.Net/Server/RespondWithAProvider.cs
index 508d8478..d2125bee 100644
--- a/src/WireMock.Net/Server/RespondWithAProvider.cs
+++ b/src/WireMock.Net/Server/RespondWithAProvider.cs
@@ -30,6 +30,8 @@ internal class RespondWithAProvider : IRespondWithAProvider
private readonly WireMockServerSettings _settings;
private readonly bool _saveToFile;
+ private bool _useWebhookFireAndForget = false;
+
public Guid Guid { get; private set; } = Guid.NewGuid();
public IWebhook[]? Webhooks { get; private set; }
@@ -57,7 +59,7 @@ internal class RespondWithAProvider : IRespondWithAProvider
/// The provider.
public void RespondWith(IResponseProvider provider)
{
- _registrationCallback(new Mapping(Guid, _title, _description, _path, _settings, _requestMatcher, provider, _priority, _scenario, _executionConditionState, _nextState, _timesInSameState, Webhooks, TimeSettings), _saveToFile);
+ _registrationCallback(new Mapping(Guid, _title, _description, _path, _settings, _requestMatcher, provider, _priority, _scenario, _executionConditionState, _nextState, _timesInSameState, Webhooks, _useWebhookFireAndForget, TimeSettings), _saveToFile);
}
///
@@ -233,6 +235,13 @@ internal class RespondWithAProvider : IRespondWithAProvider
return this;
}
+ public IRespondWithAProvider WithWebhookFireAndForget(bool useWebhooksFireAndForget)
+ {
+ _useWebhookFireAndForget = useWebhooksFireAndForget;
+
+ return this;
+ }
+
private static IWebhook InitWebhook(
string url,
string method,
diff --git a/test/WireMock.Net.Tests/Owin/WireMockMiddlewareTests.cs b/test/WireMock.Net.Tests/Owin/WireMockMiddlewareTests.cs
index 0b57c5d1..c070fc54 100644
--- a/test/WireMock.Net.Tests/Owin/WireMockMiddlewareTests.cs
+++ b/test/WireMock.Net.Tests/Owin/WireMockMiddlewareTests.cs
@@ -176,7 +176,7 @@ namespace WireMock.Net.Tests.Owin
_mappingMock.SetupGet(m => m.Provider).Returns(responseBuilder);
_mappingMock.SetupGet(m => m.Settings).Returns(settings);
- var newMappingFromProxy = new Mapping(Guid.NewGuid(), string.Empty, string.Empty, null, settings, Request.Create(), Response.Create(), 0, null, null, null, null, null, null);
+ var newMappingFromProxy = new Mapping(Guid.NewGuid(), string.Empty, string.Empty, null, settings, Request.Create(), Response.Create(), 0, null, null, null, null, null, false, null);
_mappingMock.Setup(m => m.ProvideResponseAsync(It.IsAny())).ReturnsAsync((new ResponseMessage(), newMappingFromProxy));
var requestBuilder = Request.Create().UsingAnyMethod();
@@ -230,7 +230,7 @@ namespace WireMock.Net.Tests.Owin
_mappingMock.SetupGet(m => m.Provider).Returns(responseBuilder);
_mappingMock.SetupGet(m => m.Settings).Returns(settings);
- var newMappingFromProxy = new Mapping(Guid.NewGuid(), "my-title", "my-description", null, settings, Request.Create(), Response.Create(), 0, null, null, null, null, null, null);
+ var newMappingFromProxy = new Mapping(Guid.NewGuid(), "my-title", "my-description", null, settings, Request.Create(), Response.Create(), 0, null, null, null, null, null, false, null);
_mappingMock.Setup(m => m.ProvideResponseAsync(It.IsAny())).ReturnsAsync((new ResponseMessage(), newMappingFromProxy));
var requestBuilder = Request.Create().UsingAnyMethod();
diff --git a/test/WireMock.Net.Tests/Serialization/MappingConverterTests.cs b/test/WireMock.Net.Tests/Serialization/MappingConverterTests.cs
index 5e02ad43..b54a513a 100644
--- a/test/WireMock.Net.Tests/Serialization/MappingConverterTests.cs
+++ b/test/WireMock.Net.Tests/Serialization/MappingConverterTests.cs
@@ -11,286 +11,287 @@ using WireMock.Types;
using WireMock.Util;
using Xunit;
-namespace WireMock.Net.Tests.Serialization
+namespace WireMock.Net.Tests.Serialization;
+
+public class MappingConverterTests
{
- public class MappingConverterTests
+ private readonly WireMockServerSettings _settings = new();
+
+ private readonly MappingConverter _sut;
+
+ public MappingConverterTests()
{
- private readonly WireMockServerSettings _settings = new WireMockServerSettings();
+ _sut = new MappingConverter(new MatcherMapper(_settings));
+ }
- private readonly MappingConverter _sut;
-
- public MappingConverterTests()
+ [Fact]
+ public void ToMappingModel_With_SingleWebHook()
+ {
+ // Assign
+ var request = Request.Create();
+ var response = Response.Create();
+ var webhooks = new IWebhook[]
{
- _sut = new MappingConverter(new MatcherMapper(_settings));
- }
-
- [Fact]
- public void ToMappingModel_With_SingleWebHook()
- {
- // Assign
- var request = Request.Create();
- var response = Response.Create();
- var webhooks = new IWebhook[]
+ new Webhook
{
- new Webhook
+ Request = new WebhookRequest
{
- Request = new WebhookRequest
+ Url = "https://test.com",
+ Headers = new Dictionary>
{
- Url = "https://test.com",
- Headers = new Dictionary>
- {
- { "Single", new WireMockList("x") },
- { "Multi", new WireMockList("a", "b") }
- },
- Method = "post",
- BodyData = new BodyData
- {
- BodyAsString = "b",
- DetectedBodyType = BodyType.String,
- DetectedBodyTypeFromContentType = BodyType.String
- }
+ { "Single", new WireMockList("x") },
+ { "Multi", new WireMockList("a", "b") }
+ },
+ Method = "post",
+ BodyData = new BodyData
+ {
+ BodyAsString = "b",
+ DetectedBodyType = BodyType.String,
+ DetectedBodyTypeFromContentType = BodyType.String
}
}
- };
- var mapping = new Mapping(Guid.NewGuid(), string.Empty, string.Empty, null, _settings, request, response, 0, null, null, null, null, webhooks, null);
-
- // Act
- var model = _sut.ToMappingModel(mapping);
-
- // Assert
- model.Should().NotBeNull();
- model.Priority.Should().BeNull();
-
- model.Response.BodyAsJsonIndented.Should().BeNull();
- model.Response.UseTransformer.Should().BeNull();
- model.Response.Headers.Should().BeNull();
-
- model.Webhooks.Should().BeNull();
-
- model.Webhook.Request.Method.Should().Be("post");
- model.Webhook.Request.Url.Should().Be("https://test.com");
- model.Webhook.Request.Headers.Should().HaveCount(2);
- model.Webhook.Request.Body.Should().Be("b");
- model.Webhook.Request.BodyAsJson.Should().BeNull();
- }
-
- [Fact]
- public void ToMappingModel_With_MultipleWebHooks()
- {
- // Assign
- var request = Request.Create();
- var response = Response.Create();
- var webhooks = new IWebhook[]
- {
- new Webhook
- {
- Request = new WebhookRequest
- {
- Url = "https://test1.com",
- Headers = new Dictionary>
- {
- { "One", new WireMockList("x") }
- },
- Method = "post",
- BodyData = new BodyData
- {
- BodyAsString = "1",
- DetectedBodyType = BodyType.String,
- DetectedBodyTypeFromContentType = BodyType.String
- }
- }
- },
-
- new Webhook
- {
- Request = new WebhookRequest
- {
- Url = "https://test2.com",
- Headers = new Dictionary>
- {
- { "First", new WireMockList("x") },
- { "Second", new WireMockList("a", "b") }
- },
- Method = "post",
- BodyData = new BodyData
- {
- BodyAsString = "2",
- DetectedBodyType = BodyType.String,
- DetectedBodyTypeFromContentType = BodyType.String
- }
- }
- }
- };
- var mapping = new Mapping(Guid.NewGuid(), string.Empty, string.Empty, null, _settings, request, response, 0, null, null, null, null, webhooks, null);
-
- // Act
- var model = _sut.ToMappingModel(mapping);
-
- // Assert
- model.Should().NotBeNull();
- model.Priority.Should().BeNull();
-
- model.Response.BodyAsJsonIndented.Should().BeNull();
- model.Response.UseTransformer.Should().BeNull();
- model.Response.Headers.Should().BeNull();
-
- model.Webhook.Should().BeNull();
-
- model.Webhooks[0].Request.Method.Should().Be("post");
- model.Webhooks[0].Request.Url.Should().Be("https://test1.com");
- model.Webhooks[0].Request.Headers.Should().HaveCount(1);
- model.Webhooks[0].Request.Body.Should().Be("1");
-
- model.Webhooks[1].Request.Method.Should().Be("post");
- model.Webhooks[1].Request.Url.Should().Be("https://test2.com");
- model.Webhooks[1].Request.Headers.Should().HaveCount(2);
- model.Webhooks[1].Request.Body.Should().Be("2");
- }
-
- [Fact]
- public void ToMappingModel_WithTitle_And_Description_ReturnsCorrectModel()
- {
- // Assign
- var title = "my-title";
- var description = "my-description";
- var request = Request.Create();
- var response = Response.Create();
- var mapping = new Mapping(Guid.NewGuid(), title, description, null, _settings, request, response, 0, null, null, null, null, null, null);
-
- // Act
- var model = _sut.ToMappingModel(mapping);
-
- // Assert
- model.Should().NotBeNull();
- model.Title.Should().Be(title);
- model.Description.Should().Be(description);
- }
-
- [Fact]
- public void ToMappingModel_WithPriority_ReturnsPriority()
- {
- // Assign
- var request = Request.Create();
- var response = Response.Create().WithBodyAsJson(new { x = "x" }).WithTransformer();
- var mapping = new Mapping(Guid.NewGuid(), string.Empty, string.Empty, null, _settings, request, response, 42, null, null, null, null, null, null);
-
- // Act
- var model = _sut.ToMappingModel(mapping);
-
- // Assert
- model.Should().NotBeNull();
- model.Priority.Should().Be(42);
- model.Response.UseTransformer.Should().BeTrue();
- }
-
- [Fact]
- public void ToMappingModel_WithTimeSettings_ReturnsCorrectTimeSettings()
- {
- // Assign
- var start = DateTime.Now;
- var ttl = 100;
- var end = start.AddSeconds(ttl);
- var request = Request.Create();
- var response = Response.Create();
- var timeSettings = new TimeSettings
- {
- Start = start,
- End = end,
- TTL = ttl
- };
- var mapping = new Mapping(Guid.NewGuid(), string.Empty, string.Empty, null, _settings, request, response, 42, null, null, null, null, null, timeSettings);
-
- // Act
- var model = _sut.ToMappingModel(mapping);
-
- // Assert
- model.Should().NotBeNull();
- model.TimeSettings.Should().NotBeNull();
- model.TimeSettings.Start.Should().Be(start);
- model.TimeSettings.End.Should().Be(end);
- model.TimeSettings.TTL.Should().Be(ttl);
- }
-
- [Fact]
- public void ToMappingModel_WithDelayAsTimeSpan_ReturnsCorrectModel()
- {
- // Arrange
- var tests = new[]
- {
- new { Delay = Timeout.InfiniteTimeSpan, Expected = (int) TimeSpan.MaxValue.TotalMilliseconds },
- new { Delay = TimeSpan.FromSeconds(1), Expected = 1000},
- new { Delay = TimeSpan.MaxValue, Expected = (int) TimeSpan.MaxValue.TotalMilliseconds }
- };
-
- foreach (var test in tests)
- {
- var request = Request.Create();
- var response = Response.Create().WithDelay(test.Delay);
- var mapping = new Mapping(Guid.NewGuid(), string.Empty, string.Empty, string.Empty, _settings, request, response, 42, null, null, null, null, null, null);
-
- // Act
- var model = _sut.ToMappingModel(mapping);
-
- // Assert
- model.Should().NotBeNull();
- model.Response.Delay.Should().Be(test.Expected);
}
- }
+ };
+ var mapping = new Mapping(Guid.NewGuid(), string.Empty, string.Empty, null, _settings, request, response, 0, null, null, null, null, webhooks, false, null);
- [Fact]
- public void ToMappingModel_WithDelayAsMilleSeconds_ReturnsCorrectModel()
+ // Act
+ var model = _sut.ToMappingModel(mapping);
+
+ // Assert
+ model.Should().NotBeNull();
+ model.Priority.Should().BeNull();
+
+ model.Response.BodyAsJsonIndented.Should().BeNull();
+ model.Response.UseTransformer.Should().BeNull();
+ model.Response.Headers.Should().BeNull();
+ model.UseWebhooksFireAndForget.Should().BeFalse();
+
+ model.Webhooks.Should().BeNull();
+
+ model.Webhook!.Request.Method.Should().Be("post");
+ model.Webhook.Request.Url.Should().Be("https://test.com");
+ model.Webhook.Request.Headers.Should().HaveCount(2);
+ model.Webhook.Request.Body.Should().Be("b");
+ model.Webhook.Request.BodyAsJson.Should().BeNull();
+ }
+
+ [Fact]
+ public void ToMappingModel_With_MultipleWebHooks()
+ {
+ // Assign
+ var request = Request.Create();
+ var response = Response.Create();
+ var webhooks = new IWebhook[]
+ {
+ new Webhook
+ {
+ Request = new WebhookRequest
+ {
+ Url = "https://test1.com",
+ Headers = new Dictionary>
+ {
+ { "One", new WireMockList("x") }
+ },
+ Method = "post",
+ BodyData = new BodyData
+ {
+ BodyAsString = "1",
+ DetectedBodyType = BodyType.String,
+ DetectedBodyTypeFromContentType = BodyType.String
+ }
+ }
+ },
+
+ new Webhook
+ {
+ Request = new WebhookRequest
+ {
+ Url = "https://test2.com",
+ Headers = new Dictionary>
+ {
+ { "First", new WireMockList("x") },
+ { "Second", new WireMockList("a", "b") }
+ },
+ Method = "post",
+ BodyData = new BodyData
+ {
+ BodyAsString = "2",
+ DetectedBodyType = BodyType.String,
+ DetectedBodyTypeFromContentType = BodyType.String
+ }
+ }
+ }
+ };
+ var mapping = new Mapping(Guid.NewGuid(), string.Empty, string.Empty, null, _settings, request, response, 0, null, null, null, null, webhooks, true, null);
+
+ // Act
+ var model = _sut.ToMappingModel(mapping);
+
+ // Assert
+ model.Should().NotBeNull();
+ model.Priority.Should().BeNull();
+
+ model.Response.BodyAsJsonIndented.Should().BeNull();
+ model.Response.UseTransformer.Should().BeNull();
+ model.Response.Headers.Should().BeNull();
+ model.UseWebhooksFireAndForget.Should().BeTrue();
+
+ model.Webhook.Should().BeNull();
+
+ model.Webhooks![0].Request.Method.Should().Be("post");
+ model.Webhooks[0].Request.Url.Should().Be("https://test1.com");
+ model.Webhooks[0].Request.Headers.Should().HaveCount(1);
+ model.Webhooks[0].Request.Body.Should().Be("1");
+
+ model.Webhooks[1].Request.Method.Should().Be("post");
+ model.Webhooks[1].Request.Url.Should().Be("https://test2.com");
+ model.Webhooks[1].Request.Headers.Should().HaveCount(2);
+ model.Webhooks[1].Request.Body.Should().Be("2");
+ }
+
+ [Fact]
+ public void ToMappingModel_WithTitle_And_Description_ReturnsCorrectModel()
+ {
+ // Assign
+ var title = "my-title";
+ var description = "my-description";
+ var request = Request.Create();
+ var response = Response.Create();
+ var mapping = new Mapping(Guid.NewGuid(), title, description, null, _settings, request, response, 0, null, null, null, null, null, false, null);
+
+ // Act
+ var model = _sut.ToMappingModel(mapping);
+
+ // Assert
+ model.Should().NotBeNull();
+ model.Title.Should().Be(title);
+ model.Description.Should().Be(description);
+ }
+
+ [Fact]
+ public void ToMappingModel_WithPriority_ReturnsPriority()
+ {
+ // Assign
+ var request = Request.Create();
+ var response = Response.Create().WithBodyAsJson(new { x = "x" }).WithTransformer();
+ var mapping = new Mapping(Guid.NewGuid(), string.Empty, string.Empty, null, _settings, request, response, 42, null, null, null, null, null, false, null);
+
+ // Act
+ var model = _sut.ToMappingModel(mapping);
+
+ // Assert
+ model.Should().NotBeNull();
+ model.Priority.Should().Be(42);
+ model.Response.UseTransformer.Should().BeTrue();
+ }
+
+ [Fact]
+ public void ToMappingModel_WithTimeSettings_ReturnsCorrectTimeSettings()
+ {
+ // Assign
+ var start = DateTime.Now;
+ var ttl = 100;
+ var end = start.AddSeconds(ttl);
+ var request = Request.Create();
+ var response = Response.Create();
+ var timeSettings = new TimeSettings
+ {
+ Start = start,
+ End = end,
+ TTL = ttl
+ };
+ var mapping = new Mapping(Guid.NewGuid(), string.Empty, string.Empty, null, _settings, request, response, 42, null, null, null, null, null, false, timeSettings);
+
+ // Act
+ var model = _sut.ToMappingModel(mapping);
+
+ // Assert
+ model.Should().NotBeNull();
+ model.TimeSettings!.Should().NotBeNull();
+ model.TimeSettings!.Start.Should().Be(start);
+ model.TimeSettings.End.Should().Be(end);
+ model.TimeSettings.TTL.Should().Be(ttl);
+ }
+
+ [Fact]
+ public void ToMappingModel_WithDelayAsTimeSpan_ReturnsCorrectModel()
+ {
+ // Arrange
+ var tests = new[]
+ {
+ new { Delay = Timeout.InfiniteTimeSpan, Expected = (int) TimeSpan.MaxValue.TotalMilliseconds },
+ new { Delay = TimeSpan.FromSeconds(1), Expected = 1000 },
+ new { Delay = TimeSpan.MaxValue, Expected = (int) TimeSpan.MaxValue.TotalMilliseconds }
+ };
+
+ foreach (var test in tests)
{
- // Assign
- var delay = 1000;
var request = Request.Create();
- var response = Response.Create().WithDelay(delay);
- var mapping = new Mapping(Guid.NewGuid(), string.Empty, string.Empty, null, _settings, request, response, 42, null, null, null, null, null, null);
+ var response = Response.Create().WithDelay(test.Delay);
+ var mapping = new Mapping(Guid.NewGuid(), string.Empty, string.Empty, string.Empty, _settings, request, response, 42, null, null, null, null, null, false, null);
// Act
var model = _sut.ToMappingModel(mapping);
// Assert
model.Should().NotBeNull();
- model.Response.Delay.Should().Be(delay);
- }
-
- [Fact]
- public void ToMappingModel_WithRandomMinimumDelay_ReturnsCorrectModel()
- {
- // Assign
- int minimumDelay = 1000;
- var request = Request.Create();
- var response = Response.Create().WithRandomDelay(minimumDelay);
- var mapping = new Mapping(Guid.NewGuid(), string.Empty, string.Empty, null, _settings, request, response, 42, null, null, null, null, null, null);
-
- // Act
- var model = _sut.ToMappingModel(mapping);
-
- // Assert
- model.Should().NotBeNull();
- model.Response.Delay.Should().BeNull();
- model.Response.MinimumRandomDelay.Should().Be(minimumDelay);
- model.Response.MaximumRandomDelay.Should().Be(60_000);
- }
-
- [Fact]
- public void ToMappingModel_WithRandomDelay_ReturnsCorrectModel()
- {
- // Assign
- int minimumDelay = 1000;
- int maximumDelay = 2000;
- var request = Request.Create();
- var response = Response.Create().WithRandomDelay(minimumDelay, maximumDelay);
- var mapping = new Mapping(Guid.NewGuid(), string.Empty, string.Empty, null, _settings, request, response, 42, null, null, null, null, null, null);
-
- // Act
- var model = _sut.ToMappingModel(mapping);
-
- // Assert
- model.Should().NotBeNull();
- model.Response.Delay.Should().BeNull();
- model.Response.MinimumRandomDelay.Should().Be(minimumDelay);
- model.Response.MaximumRandomDelay.Should().Be(maximumDelay);
+ model.Response.Delay.Should().Be(test.Expected);
}
}
+
+ [Fact]
+ public void ToMappingModel_WithDelayAsMilleSeconds_ReturnsCorrectModel()
+ {
+ // Assign
+ var delay = 1000;
+ var request = Request.Create();
+ var response = Response.Create().WithDelay(delay);
+ var mapping = new Mapping(Guid.NewGuid(), string.Empty, string.Empty, null, _settings, request, response, 42, null, null, null, null, null, false, null);
+
+ // Act
+ var model = _sut.ToMappingModel(mapping);
+
+ // Assert
+ model.Should().NotBeNull();
+ model.Response.Delay.Should().Be(delay);
+ }
+
+ [Fact]
+ public void ToMappingModel_WithRandomMinimumDelay_ReturnsCorrectModel()
+ {
+ // Assign
+ int minimumDelay = 1000;
+ var request = Request.Create();
+ var response = Response.Create().WithRandomDelay(minimumDelay);
+ var mapping = new Mapping(Guid.NewGuid(), string.Empty, string.Empty, null, _settings, request, response, 42, null, null, null, null, null, false, null);
+
+ // Act
+ var model = _sut.ToMappingModel(mapping);
+
+ // Assert
+ model.Should().NotBeNull();
+ model.Response.Delay.Should().BeNull();
+ model.Response.MinimumRandomDelay.Should().Be(minimumDelay);
+ model.Response.MaximumRandomDelay.Should().Be(60_000);
+ }
+
+ [Fact]
+ public void ToMappingModel_WithRandomDelay_ReturnsCorrectModel()
+ {
+ // Assign
+ int minimumDelay = 1000;
+ int maximumDelay = 2000;
+ var request = Request.Create();
+ var response = Response.Create().WithRandomDelay(minimumDelay, maximumDelay);
+ var mapping = new Mapping(Guid.NewGuid(), string.Empty, string.Empty, null, _settings, request, response, 42, null, null, null, null, null, false, null);
+
+ // Act
+ var model = _sut.ToMappingModel(mapping);
+
+ // Assert
+ model.Should().NotBeNull();
+ model.Response.Delay.Should().BeNull();
+ model.Response.MinimumRandomDelay.Should().Be(minimumDelay);
+ model.Response.MaximumRandomDelay.Should().Be(maximumDelay);
+ }
}
\ No newline at end of file
diff --git a/test/WireMock.Net.Tests/Serialization/WebhookMapperTests.cs b/test/WireMock.Net.Tests/Serialization/WebhookMapperTests.cs
index dc6df4e1..54d35956 100644
--- a/test/WireMock.Net.Tests/Serialization/WebhookMapperTests.cs
+++ b/test/WireMock.Net.Tests/Serialization/WebhookMapperTests.cs
@@ -1,101 +1,145 @@
-using System.Collections.Generic;
+using System.Collections.Generic;
using FluentAssertions;
using WireMock.Admin.Mappings;
+using WireMock.Models;
using WireMock.Serialization;
using WireMock.Types;
+using WireMock.Util;
using Xunit;
-namespace WireMock.Net.Tests.Serialization
+namespace WireMock.Net.Tests.Serialization;
+
+public class WebhookMapperTests
{
- public class WebhookMapperTests
+ [Fact]
+ public void WebhookMapper_Map_WebhookModel_BodyAsString_And_UseTransformerIsFalse()
{
- [Fact]
- public void WebhookMapper_Map_Model_BodyAsString_And_UseTransformerIsFalse()
+ // Assign
+ var model = new WebhookModel
{
- // Assign
- var model = new WebhookModel
+ Request = new WebhookRequestModel
{
- Request = new WebhookRequestModel
+ Url = "https://localhost",
+ Method = "get",
+ Headers = new Dictionary
{
- Url = "https://localhost",
- Method = "get",
- Headers = new Dictionary
- {
- { "x", "y" }
- },
- Body = "test",
- UseTransformer = false
- }
- };
+ { "x", "y" }
+ },
+ Body = "test",
+ UseTransformer = false
+ }
+ };
- var result = WebhookMapper.Map(model);
+ var result = WebhookMapper.Map(model);
- result.Request.Url.Should().Be("https://localhost");
- result.Request.Method.Should().Be("get");
- result.Request.Headers.Should().HaveCount(1);
- result.Request.BodyData.BodyAsJson.Should().BeNull();
- result.Request.BodyData.BodyAsString.Should().Be("test");
- result.Request.BodyData.DetectedBodyType.Should().Be(BodyType.String);
- result.Request.UseTransformer.Should().BeNull();
- }
-
- [Fact]
- public void WebhookMapper_Map_Model_BodyAsString_And_UseTransformerIsTrue()
- {
- // Assign
- var model = new WebhookModel
- {
- Request = new WebhookRequestModel
- {
- Url = "https://localhost",
- Method = "get",
- Headers = new Dictionary
- {
- { "x", "y" }
- },
- Body = "test",
- UseTransformer = true
- }
- };
-
- var result = WebhookMapper.Map(model);
-
- result.Request.Url.Should().Be("https://localhost");
- result.Request.Method.Should().Be("get");
- result.Request.Headers.Should().HaveCount(1);
- result.Request.BodyData.BodyAsJson.Should().BeNull();
- result.Request.BodyData.BodyAsString.Should().Be("test");
- result.Request.BodyData.DetectedBodyType.Should().Be(BodyType.String);
- result.Request.UseTransformer.Should().BeTrue();
- result.Request.TransformerType.Should().Be(TransformerType.Handlebars);
- }
-
- [Fact]
- public void WebhookMapper_Map_Model_BodyAsJson()
- {
- // Assign
- var model = new WebhookModel
- {
- Request = new WebhookRequestModel
- {
- Url = "https://localhost",
- Method = "get",
- Headers = new Dictionary
- {
- { "x", "y" }
- },
- BodyAsJson = new { n = 12345 }
- }
- };
-
- var result = WebhookMapper.Map(model);
-
- result.Request.Url.Should().Be("https://localhost");
- result.Request.Method.Should().Be("get");
- result.Request.Headers.Should().HaveCount(1);
- result.Request.BodyData.BodyAsString.Should().BeNull();
- result.Request.BodyData.BodyAsJson.Should().NotBeNull();
- result.Request.BodyData.DetectedBodyType.Should().Be(BodyType.Json);
- }
+ result.Request.Url.Should().Be("https://localhost");
+ result.Request.Method.Should().Be("get");
+ result.Request.Headers.Should().HaveCount(1);
+ result.Request.BodyData!.BodyAsJson.Should().BeNull();
+ result.Request.BodyData.BodyAsString.Should().Be("test");
+ result.Request.BodyData.DetectedBodyType.Should().Be(BodyType.String);
+ result.Request.UseTransformer.Should().BeNull();
}
-}
+
+ [Fact]
+ public void WebhookMapper_Map_WebhookModel_BodyAsString_And_UseTransformerIsTrue()
+ {
+ // Assign
+ var model = new WebhookModel
+ {
+ Request = new WebhookRequestModel
+ {
+ Url = "https://localhost",
+ Method = "get",
+ Headers = new Dictionary
+ {
+ { "x", "y" }
+ },
+ Body = "test",
+ UseTransformer = true
+ }
+ };
+
+ var result = WebhookMapper.Map(model);
+
+ result.Request.Url.Should().Be("https://localhost");
+ result.Request.Method.Should().Be("get");
+ result.Request.Headers.Should().HaveCount(1);
+ result.Request.BodyData!.BodyAsJson.Should().BeNull();
+ result.Request.BodyData.BodyAsString.Should().Be("test");
+ result.Request.BodyData.DetectedBodyType.Should().Be(BodyType.String);
+ result.Request.UseTransformer.Should().BeTrue();
+ result.Request.TransformerType.Should().Be(TransformerType.Handlebars);
+ }
+
+ [Fact]
+ public void WebhookMapper_Map_WebhookModel_BodyAsJson()
+ {
+ // Assign
+ var model = new WebhookModel
+ {
+ Request = new WebhookRequestModel
+ {
+ Url = "https://localhost",
+ Method = "get",
+ Headers = new Dictionary
+ {
+ { "x", "y" }
+ },
+ BodyAsJson = new { n = 12345 },
+ Delay = 4,
+ MinimumRandomDelay = 5,
+ MaximumRandomDelay = 6
+ },
+ };
+
+ var result = WebhookMapper.Map(model);
+
+ result.Request.Url.Should().Be("https://localhost");
+ result.Request.Method.Should().Be("get");
+ result.Request.Headers.Should().HaveCount(1);
+ result.Request.BodyData!.BodyAsString.Should().BeNull();
+ result.Request.BodyData.BodyAsJson.Should().NotBeNull();
+ result.Request.BodyData.DetectedBodyType.Should().Be(BodyType.Json);
+ result.Request.Delay.Should().Be(4);
+ result.Request.MinimumRandomDelay.Should().Be(5);
+ result.Request.MaximumRandomDelay.Should().Be(6);
+ }
+
+ [Fact]
+ public void WebhookMapper_Map_Webhook_To_Model()
+ {
+ // Assign
+ var webhook = new Webhook
+ {
+ Request = new WebhookRequest
+ {
+ Url = "https://localhost",
+ Method = "get",
+ Headers = new Dictionary>
+ {
+ { "x", new WireMockList("y") }
+ },
+ BodyData = new BodyData
+ {
+ BodyAsJson = new { n = 12345 },
+ DetectedBodyType = BodyType.Json,
+ DetectedBodyTypeFromContentType = BodyType.Json
+ },
+ Delay = 4,
+ MinimumRandomDelay = 5,
+ MaximumRandomDelay = 6
+ }
+ };
+
+ var result = WebhookMapper.Map(webhook);
+
+ result.Request.Url.Should().Be("https://localhost");
+ result.Request.Method.Should().Be("get");
+ result.Request.Headers.Should().HaveCount(1);
+ result.Request.BodyAsJson.Should().NotBeNull();
+ result.Request.Delay.Should().Be(4);
+ result.Request.MinimumRandomDelay.Should().Be(5);
+ result.Request.MaximumRandomDelay.Should().Be(6);
+ }
+}
\ No newline at end of file