Compare commits

..

11 Commits
1.5.4 ... 1.5.7

Author SHA1 Message Date
Stef Heyenrath
14dd619763 1.5.7 2022-10-11 09:57:11 +02:00
Stef Heyenrath
430c01a461 Add implicit operators to WireMockList (#823)
* Add implicit operators to WireMockList

* .
2022-10-01 10:50:18 +02:00
Stef Heyenrath
f7b04f3234 Add UseDefinedRequestMatchers to ProxyAndRecordSettings (#821)
* .

* UseDefinedRequestMatchers

* ok

* .

* ClientIP

* t

* fix ut

* .

* cf

* cf2
2022-09-30 11:25:11 +02:00
Stef Heyenrath
c0b18631a3 Add option to run the server on http & https (#818)
* HostingProtocol.HttpAndHttps

* .

* .

* .

* HostingScheme
2022-09-26 14:24:45 +02:00
Stef Heyenrath
fd996ab4ed 1.5.6 2022-09-12 20:45:26 +02:00
Stef Heyenrath
a57626c63a 1.5.6 2022-09-12 20:38:45 +02:00
Stef Heyenrath
98a0f2fa28 WebHook : UseFireAndForget + Delay (#803)
* UseFireAndForget

* ...

* delay

* async

* updated code accorsing to proposal

* Change nuget to package reference for WireMock.Net.Console.Net472.Classic, move the new FireAndForget into the main mapping, out of individual webhook mappings making it all or nothing, update tests, change Middleware to await or not the firing of all webhooks. Update models as needed. (#804)

Co-authored-by: Matt Philmon <Matt_Philmon@carmax.com>

* small update

* Tweak middleware and fix bug in example (#806)

Co-authored-by: Matt Philmon <Matt_Philmon@carmax.com>

* .ConfigureAwait(false)

Co-authored-by: mattisking <mattisking@gmail.com>
Co-authored-by: Matt Philmon <Matt_Philmon@carmax.com>
2022-09-12 20:30:40 +02:00
Stef Heyenrath
13a06b9b38 1.5.5 2022-09-03 08:57:30 +02:00
Stef Heyenrath
74480c8ba9 Add support to use 'mapping' object in in reponse templating (#798)
* mapping

* .

* .
2022-09-03 08:52:05 +02:00
Rafael Moreira Fonseca
862c04e722 Add assertions for request methods (#802)
* Add assertions for request methods

* Fix assertions tests when using connect method

* Remove unnecessary clear and fix assert condition
2022-09-03 08:49:39 +02:00
dependabot[bot]
cd93422554 Bump Microsoft.Owin from 4.1.1 to 4.2.2 in /src/WireMock.Net (#800)
Bumps [Microsoft.Owin](https://github.com/aspnet/AspNetKatana) from 4.1.1 to 4.2.2.
- [Release notes](https://github.com/aspnet/AspNetKatana/releases)
- [Commits](https://github.com/aspnet/AspNetKatana/compare/v4.1.1...v4.2.2)

---
updated-dependencies:
- dependency-name: Microsoft.Owin
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-08-31 21:19:37 +02:00
86 changed files with 3687 additions and 2726 deletions

View File

@@ -1,3 +1,21 @@
# 1.5.7 (11 October 2022)
- [#818](https://github.com/WireMock-Net/WireMock.Net/pull/818) - Add option to run the server on http &amp; https [feature] contributed by [StefH](https://github.com/StefH)
- [#821](https://github.com/WireMock-Net/WireMock.Net/pull/821) - Add UseDefinedRequestMatchers to ProxyAndRecordSettings [feature] contributed by [StefH](https://github.com/StefH)
- [#823](https://github.com/WireMock-Net/WireMock.Net/pull/823) - Add implicit operators to WireMockList contributed by [StefH](https://github.com/StefH)
- [#819](https://github.com/WireMock-Net/WireMock.Net/issues/819) - Can I preserve Mapping title and matchers for proxy response? [feature]
# 1.5.6 (12 September 2022)
- [#803](https://github.com/WireMock-Net/WireMock.Net/pull/803) - WebHook : UseFireAndForget + Delay [feature] contributed by [StefH](https://github.com/StefH)
- [#804](https://github.com/WireMock-Net/WireMock.Net/pull/804) - Change nuget to package reference for WireMock.Net.Console.Net472.Cla&#8230; [feature] contributed by [mattisking](https://github.com/mattisking)
- [#806](https://github.com/WireMock-Net/WireMock.Net/pull/806) - Tweak middleware and fix bug in example [feature] contributed by [mattisking](https://github.com/mattisking)
- [#801](https://github.com/WireMock-Net/WireMock.Net/issues/801) - Webhook Delays [feature]
# 1.5.5 (03 September 2022)
- [#798](https://github.com/WireMock-Net/WireMock.Net/pull/798) - Add support to use 'mapping' object in in reponse templating [feature] contributed by [StefH](https://github.com/StefH)
- [#800](https://github.com/WireMock-Net/WireMock.Net/pull/800) - Bump Microsoft.Owin from 4.1.1 to 4.2.2 in /src/WireMock.Net (net46) [dependencies] contributed by [dependabot[bot]](https://github.com/apps/dependabot)
- [#802](https://github.com/WireMock-Net/WireMock.Net/pull/802) - Add assertions for request methods contributed by [rafaelmfonseca](https://github.com/rafaelmfonseca)
- [#772](https://github.com/WireMock-Net/WireMock.Net/issues/772) - How to get matched mapping by HttpRequest or HttpRequestMessage [feature]
# 1.5.4 (24 August 2022)
- [#778](https://github.com/WireMock-Net/WireMock.Net/pull/778) - Fix Proxying when StartAdminInterface=true [bug] contributed by [StefH](https://github.com/StefH)
- [#781](https://github.com/WireMock-Net/WireMock.Net/pull/781) - Update some NuGet packages [feature] contributed by [StefH](https://github.com/StefH)

View File

@@ -4,7 +4,7 @@
</PropertyGroup>
<PropertyGroup>
<VersionPrefix>1.5.4</VersionPrefix>
<VersionPrefix>1.5.7</VersionPrefix>
<PackageIcon>WireMock.Net-Logo.png</PackageIcon>
<PackageProjectUrl>https://github.com/WireMock-Net/WireMock.Net</PackageProjectUrl>
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>

View File

@@ -1,6 +1,6 @@
rem https://github.com/StefH/GitHubReleaseNotes
SET version=1.5.4
SET version=1.5.7
GitHubReleaseNotes --output CHANGELOG.md --skip-empty-releases --exclude-labels question invalid doc duplicate --version %version% --token %GH_TOKEN%

View File

@@ -1,16 +1,7 @@
# 1.5.4 (24 August 2022)
- #778 Fix Proxying when StartAdminInterface=true [bug]
- #781 Update some NuGet packages [feature]
- #783 Fix WithBody when using Pact and added more nullable annotations [feature]
- #787 Add support for PEM certificates
- #789 Add support for Matcher.Pattern in Pact Body mapping [feature]
- #790 Add Response.WithBody with IJsonConverter [feature]
- #795 Add check for duplicate Guids when posting multiple mappings in one request
- #797 Fix WithHeader when using RejectOnMatch [bug]
- #775 When &quot;StartAdminInterface&quot; is true then each time is generated new mapping from the proxy [bug]
- #784 Response body is missing in generated pact file when IBodyResponseBuilder.WithBody is used [bug]
- #785 Support for PEM certificates when using ssl [feature]
- #788 Request body is missing in generated pact file for requests that include matching on request body [bug]
- #796 RequestMessageHeaderMatcher with MatchBehaviour.RejectOnMatch reverses match results twice [bug]
# 1.5.7 (11 October 2022)
- #818 Add option to run the server on http &amp; https [feature]
- #821 Add UseDefinedRequestMatchers to ProxyAndRecordSettings [feature]
- #823 Add implicit operators to WireMockList
- #819 Can I preserve Mapping title and matchers for proxy response? [feature]
The full release notes can be found here: https://github.com/WireMock-Net/WireMock.Net/blob/master/CHANGELOG.md

View File

@@ -30,5 +30,6 @@
<s:Boolean x:Key="/Default/UserDictionary/Words/=Webhooks/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=wiremock/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=wiremockserver/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Xeger/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=xunit/@EntryIndexedValue">True</s:Boolean>
</wpf:ResourceDictionary>

View File

@@ -1,22 +1,21 @@
using System.IO;
using System.IO;
using System.Reflection;
using log4net;
using log4net.Config;
using log4net.Repository;
using WireMock.Net.ConsoleApplication;
namespace WireMock.Net.Console.NETCoreApp
namespace WireMock.Net.Console.NETCoreApp;
static class Program
{
static class Program
private static readonly ILoggerRepository LogRepository = LogManager.GetRepository(Assembly.GetEntryAssembly());
private static readonly ILog Log = LogManager.GetLogger(typeof(Program));
static void Main(params string[] args)
{
private static readonly ILoggerRepository LogRepository = LogManager.GetRepository(Assembly.GetEntryAssembly());
private static readonly ILog Log = LogManager.GetLogger(typeof(Program));
XmlConfigurator.Configure(LogRepository, new FileInfo("log4net.config"));
static void Main(params string[] args)
{
XmlConfigurator.Configure(LogRepository, new FileInfo("log4net.config"));
MainApp.Run();
}
MainApp.Run();
}
}

View File

@@ -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;
@@ -39,6 +40,19 @@ namespace WireMock.Net.ConsoleApplication
var s = WireMockServer.Start();
s.Stop();
var httpAndHttpsWithPort = WireMockServer.Start(new WireMockServerSettings
{
HostingScheme = HostingScheme.HttpAndHttps,
Port = 12399
});
httpAndHttpsWithPort.Stop();
var httpAndHttpsFree = WireMockServer.Start(new WireMockServerSettings
{
HostingScheme = HostingScheme.HttpAndHttps
});
httpAndHttpsFree.Stop();
string url1 = "http://localhost:9091/";
string url2 = "http://localhost:9092/";
string url3 = "https://localhost:9443/";
@@ -576,6 +590,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");

View File

@@ -1,15 +1,14 @@
using System.IO;
using System.IO;
using log4net.Config;
namespace WireMock.Net.ConsoleApplication
{
static class Program
{
static void Main(params string[] args)
{
XmlConfigurator.Configure(new FileInfo("log4net.config"));
namespace WireMock.Net.ConsoleApplication;
MainApp.Run();
}
static class Program
{
static void Main(params string[] args)
{
XmlConfigurator.Configure(new FileInfo("log4net.config"));
MainApp.Run();
}
}

View File

@@ -80,7 +80,6 @@
<None Include="App.config">
<SubType>Designer</SubType>
</None>
<None Include="libman.json" />
<None Include="log4net.config">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>

View File

@@ -342,15 +342,6 @@
<Reference Include="TinyMapper, Version=3.0.1.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\packages\TinyMapper.3.0.3\lib\net40\TinyMapper.dll</HintPath>
</Reference>
<Reference Include="WireMock.Net, Version=1.5.3.0, Culture=neutral, PublicKeyToken=c8d65537854e1f03, processorArchitecture=MSIL">
<HintPath>..\..\packages\WireMock.Net.1.5.3\lib\net461\WireMock.Net.dll</HintPath>
</Reference>
<Reference Include="WireMock.Net.Abstractions, Version=1.5.3.0, Culture=neutral, PublicKeyToken=c8d65537854e1f03, processorArchitecture=MSIL">
<HintPath>..\..\packages\WireMock.Net.Abstractions.1.5.3\lib\net451\WireMock.Net.Abstractions.dll</HintPath>
</Reference>
<Reference Include="WireMock.Org.Abstractions, Version=1.5.3.0, Culture=neutral, PublicKeyToken=c8d65537854e1f03, processorArchitecture=MSIL">
<HintPath>..\..\packages\WireMock.Org.Abstractions.1.5.3\lib\net45\WireMock.Org.Abstractions.dll</HintPath>
</Reference>
<Reference Include="XPath2, Version=1.1.3.0, Culture=neutral, PublicKeyToken=463c6d7fb740c7e5, processorArchitecture=MSIL">
<HintPath>..\..\packages\XPath2.1.1.3\lib\net452\XPath2.dll</HintPath>
</Reference>
@@ -388,6 +379,16 @@
<None Include="App.config" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\WireMock.Net.Abstractions\WireMock.Net.Abstractions.csproj">
<Project>{b6269aac-170a-4346-8b9a-579ded3d9a94}</Project>
<Name>WireMock.Net.Abstractions</Name>
</ProjectReference>
<ProjectReference Include="..\..\src\WireMock.Net\WireMock.Net.csproj">
<Project>{d3804228-91f4-4502-9595-39584e5a01ad}</Project>
<Name>WireMock.Net</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>

View File

@@ -147,9 +147,6 @@
<package id="System.Threading.Tasks.Extensions" version="4.5.1" targetFramework="net472" />
<package id="System.ValueTuple" version="4.5.0" targetFramework="net472" />
<package id="TinyMapper" version="3.0.3" targetFramework="net472" />
<package id="WireMock.Net" version="1.5.3" targetFramework="net472" />
<package id="WireMock.Net.Abstractions" version="1.5.3" targetFramework="net472" />
<package id="WireMock.Org.Abstractions" version="1.5.3" targetFramework="net472" />
<package id="XPath2" version="1.1.3" targetFramework="net472" />
<package id="XPath2.Extensions" version="1.1.3" targetFramework="net472" />
</packages>

View File

@@ -1,8 +1,16 @@
{
"profiles": {
"WireMock.Net.StandAlone.NETCoreApp": {
"commandName": "Project",
"commandLineArgs": "--Urls http://localhost:9091 --CorsPolicyOptions AllowAll --WireMockLogger WireMockConsoleLogger"
"profiles": {
"WireMock.Net.StandAlone.NETCoreApp": {
"commandName": "Project",
"commandLineArgs": "--Urls http://localhost:9091 --CorsPolicyOptions AllowAll --WireMockLogger WireMockConsoleLogger"
},
"WireMock.Net.StandAlone.NETCoreAppNoPort": {
"commandName": "Project",
"commandLineArgs": "--CorsPolicyOptions AllowAll --WireMockLogger WireMockConsoleLogger"
},
"WireMock.Net.StandAlone.NETCoreAppWithHostingProtocol": {
"commandName": "Project",
"commandLineArgs": "--HostingProtocol HttpAndHttps --CorsPolicyOptions AllowAll --WireMockLogger WireMockConsoleLogger"
}
}
}
}

View File

@@ -1,27 +1,26 @@
using System;
using System.IO;
using System.Linq;
using log4net.Config;
using WireMock.Server;
using WireMock.Settings;
namespace WireMock.Net.StandAlone.Net452
{
public class Program
{
static void Main(params string[] args)
{
XmlConfigurator.Configure(new FileInfo("log4net.config"));
if (WireMockServerSettingsParser.TryParseArguments(args, out var settings))
{
settings.Logger.Debug("WireMock.Net server arguments [{0}]", string.Join(", ", args.Select(a => $"'{a}'")));
using System;
using System.IO;
using System.Linq;
using log4net.Config;
using WireMock.Server;
using WireMock.Settings;
WireMockServer.Start(settings);
namespace WireMock.Net.StandAlone.Net452;
Console.WriteLine("Press any key to stop the server");
Console.ReadKey();
}
}
}
public class Program
{
static void Main(params string[] args)
{
XmlConfigurator.Configure(new FileInfo("log4net.config"));
if (WireMockServerSettingsParser.TryParseArguments(args, out var settings))
{
Console.WriteLine("WireMock.Net server arguments [{0}]", string.Join(", ", args.Select(a => $"'{a}'")));
WireMockServer.Start(settings);
Console.WriteLine("Press any key to stop the server");
Console.ReadKey();
}
}
}

View File

@@ -1,23 +1,22 @@
using System;
using System.Linq;
using WireMock.Server;
using WireMock.Settings;
namespace WireMock.Net.StandAlone.Net461
{
static class Program
{
static void Main(string[] args)
{
if (WireMockServerSettingsParser.TryParseArguments(args, out var settings))
{
settings.Logger.Debug("WireMock.Net server arguments [{0}]", string.Join(", ", args.Select(a => $"'{a}'")));
using System;
using System.Linq;
using WireMock.Server;
using WireMock.Settings;
WireMockServer.Start(settings);
namespace WireMock.Net.StandAlone.Net461;
Console.WriteLine("Press any key to stop the server");
Console.ReadKey();
}
}
}
static class Program
{
static void Main(string[] args)
{
if (WireMockServerSettingsParser.TryParseArguments(args, out var settings))
{
Console.WriteLine("WireMock.Net server arguments [{0}]", string.Join(", ", args.Select(a => $"'{a}'")));
WireMockServer.Start(settings);
Console.WriteLine("Press any key to stop the server");
Console.ReadKey();
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

@@ -1,31 +1,39 @@
using System.Collections.Generic;
namespace WireMock.Admin.Mappings
namespace WireMock.Admin.Mappings;
/// <summary>
/// Cookie Model
/// </summary>
[FluentBuilder.AutoGenerateBuilder]
public class CookieModel
{
/// <summary>
/// Cookie Model
/// Gets or sets the name.
/// </summary>
[FluentBuilder.AutoGenerateBuilder]
public class CookieModel
{
/// <summary>
/// Gets or sets the name.
/// </summary>
public string Name { get; set; } = null!;
public string Name { get; set; } = null!;
/// <summary>
/// Gets or sets the matchers.
/// </summary>
public IList<MatcherModel>? Matchers { get; set; }
/// <summary>
/// Gets or sets the matchers.
/// </summary>
public IList<MatcherModel>? Matchers { get; set; }
/// <summary>
/// Gets or sets the ignore case.
/// </summary>
public bool? IgnoreCase { get; set; }
/// <summary>
/// Gets or sets the ignore case.
/// </summary>
public bool? IgnoreCase { get; set; }
/// <summary>
/// Reject on match.
/// </summary>
public bool? RejectOnMatch { get; set; }
}
/// <summary>
/// Reject on match.
/// </summary>
public bool? RejectOnMatch { get; set; }
/// <summary>
/// The Operator to use when matchers are defined. [Optional]
/// - null = Same as "or".
/// - "or" = Only one pattern should match.
/// - "and" = All patterns should match.
/// - "average" = The average value from all patterns.
/// </summary>
public string? MatchOperator { get; set; }
}

View File

@@ -74,4 +74,9 @@ public class MappingModel
/// The Webhooks.
/// </summary>
public WebhookModel[]? Webhooks { get; set; }
/// <summary>
/// Fire and forget for webhooks.
/// </summary>
public bool? UseWebhooksFireAndForget { get; set; }
}

View File

@@ -1,14 +1,13 @@
namespace WireMock.Admin.Mappings
namespace WireMock.Admin.Mappings;
/// <summary>
/// The Webhook
/// </summary>
[FluentBuilder.AutoGenerateBuilder]
public class WebhookModel
{
/// <summary>
/// The Webhook
/// The Webhook Request.
/// </summary>
[FluentBuilder.AutoGenerateBuilder]
public class WebhookModel
{
/// <summary>
/// The Webhook Request.
/// </summary>
public WebhookRequestModel Request { get; set; }
}
public WebhookRequestModel Request { get; set; } = null!;
}

View File

@@ -11,12 +11,12 @@ public class WebhookRequestModel
/// <summary>
/// Gets or sets the Url.
/// </summary>
public string Url { get; set; }
public string Url { get; set; } = null!;
/// <summary>
/// The method
/// </summary>
public string Method { get; set; }
public string Method { get; set; } = null!;
/// <summary>
/// Gets or sets the headers.
@@ -47,4 +47,19 @@ public class WebhookRequestModel
/// The ReplaceNodeOptions to use when transforming a JSON node.
/// </summary>
public string? TransformerReplaceNodeOptions { get; set; }
/// <summary>
/// Gets or sets the delay in milliseconds.
/// </summary>
public int? Delay { get; set; }
/// <summary>
/// Gets or sets the minimum random delay in milliseconds.
/// </summary>
public int? MinimumRandomDelay { get; set; }
/// <summary>
/// Gets or sets the maximum random delay in milliseconds.
/// </summary>
public int? MaximumRandomDelay { get; set; }
}

View File

@@ -54,5 +54,14 @@ namespace WireMock.Admin.Settings
/// Prefer the Proxy Mapping over the saved Mapping (in case SaveMapping is set to <c>true</c>).
/// </summary>
// public bool PreferProxyMapping { get; set; }
/// <summary>
/// When SaveMapping is set to <c>true</c>, this setting can be used to control the behavior of the generated request matchers for the new mapping.
/// - <c>false</c>, the default matchers will be used.
/// - <c>true</c>, the defined mappings in the request wil be used for the new mapping.
///
/// Default value is false.
/// </summary>
public bool UseDefinedRequestMatchers { get; set; }
}
}

View File

@@ -2,46 +2,60 @@ using System.Collections.Generic;
using WireMock.Types;
using WireMock.Util;
namespace WireMock.Models
namespace WireMock.Models;
/// <summary>
/// IWebhookRequest
/// </summary>
public interface IWebhookRequest
{
/// <summary>
/// IWebhookRequest
/// The Webhook Url.
/// </summary>
public interface IWebhookRequest
{
/// <summary>
/// The Webhook Url.
/// </summary>
string Url { get; set; }
string Url { get; set; }
/// <summary>
/// The method to use.
/// </summary>
string Method { get; set; }
/// <summary>
/// The method to use.
/// </summary>
string Method { get; set; }
/// <summary>
/// The Headers to send.
/// </summary>
IDictionary<string, WireMockList<string>>? Headers { get; }
/// <summary>
/// The Headers to send.
/// </summary>
IDictionary<string, WireMockList<string>>? Headers { get; }
/// <summary>
/// The body to send.
/// </summary>
IBodyData? BodyData { get; set; }
/// <summary>
/// The body to send.
/// </summary>
IBodyData? BodyData { get; set; }
/// <summary>
/// Use Transformer.
/// </summary>
bool? UseTransformer { get; set; }
/// <summary>
/// Use Transformer.
/// </summary>
bool? UseTransformer { get; set; }
/// <summary>
/// The transformer type.
/// </summary>
TransformerType TransformerType { get; set; }
/// <summary>
/// The transformer type.
/// </summary>
TransformerType TransformerType { get; set; }
/// <summary>
/// The ReplaceNodeOptions to use when transforming a JSON node.
/// </summary>
ReplaceNodeOptions TransformerReplaceNodeOptions { get; set; }
}
/// <summary>
/// The ReplaceNodeOptions to use when transforming a JSON node.
/// </summary>
ReplaceNodeOptions TransformerReplaceNodeOptions { get; set; }
/// <summary>
/// Gets or sets the delay in milliseconds.
/// </summary>
int? Delay { get; set; }
/// <summary>
/// Gets or sets the minimum random delay in milliseconds.
/// </summary>
int? MinimumRandomDelay { get; set; }
/// <summary>
/// Gets or sets the maximum random delay in milliseconds.
/// </summary>
int? MaximumRandomDelay { get; set; }
}

View File

@@ -0,0 +1,15 @@
using System;
namespace WireMock.Types;
[Flags]
public enum HostingScheme
{
None = 0x0,
Http = 0x1,
Https = 0x2,
HttpAndHttps = Http | Https
}

View File

@@ -1,44 +1,69 @@
using System.Collections.Generic;
using System.Linq;
using System.Collections.Generic;
namespace WireMock.Types
namespace WireMock.Types;
/// <summary>
/// A special List which overrides the ToString() to return first value.
/// </summary>
/// <typeparam name="T">The generic type</typeparam>
/// <seealso cref="List{T}" />
public class WireMockList<T> : List<T>
{
/// <summary>
/// A special List which overrides the ToString() to return first value.
/// Initializes a new instance of the <see cref="WireMockList{T}"/> class.
/// </summary>
/// <typeparam name="T">The generic type</typeparam>
/// <seealso cref="List{T}" />
public class WireMockList<T> : List<T>
public WireMockList()
{
/// <summary>
/// Initializes a new instance of the <see cref="WireMockList{T}"/> class.
/// </summary>
public WireMockList()
{
}
}
/// <summary>
/// Initializes a new instance of the <see cref="WireMockList{T}"/> class.
/// </summary>
/// <param name="collection">The collection whose elements are copied to the new list.</param>
public WireMockList(params T[] collection) : base(collection)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="WireMockList{T}"/> class.
/// </summary>
/// <param name="collection">The collection whose elements are copied to the new list.</param>
public WireMockList(params T[] collection) : base(collection)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="WireMockList{T}"/> class.
/// </summary>
/// <param name="collection">The collection whose elements are copied to the new list.</param>
public WireMockList(IEnumerable<T> collection) : base(collection)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="WireMockList{T}"/> class.
/// </summary>
/// <param name="collection">The collection whose elements are copied to the new list.</param>
public WireMockList(IEnumerable<T> collection) : base(collection)
{
}
/// <summary>
/// Returns a <see cref="string" /> that represents this instance.
/// </summary>
public override string ToString()
/// <summary>
/// Operator for setting T
/// </summary>
/// <param name="value">The value to set.</param>
public static implicit operator WireMockList<T>(T value) => new(value);
/// <summary>
/// Operator for setting T[]
/// </summary>
/// <param name="values">The values to set.</param>
public static implicit operator WireMockList<T>(T[] values) => new(values);
/// <summary>
/// Returns a <see cref="string" /> that represents this instance.
/// </summary>
public override string ToString()
{
switch (Count)
{
return this.Any() ? this.First().ToString() : base.ToString();
case 0:
return string.Empty;
case 1:
if (this[0] is string strValue)
{
return strValue;
}
return this[0]?.ToString();
default:
return base.ToString();
}
}
}

View File

@@ -29,7 +29,7 @@ public class WireMockAssertions
"Expected {context:wiremockserver} to have been called at address matching the absolute url {0}{reason}, but no calls were made.",
absoluteUrl)
.Then
.ForCondition(x => _callsCount == null && x.Any(y => y.AbsoluteUrl == absoluteUrl) || _callsCount == x.Count(y => y.AbsoluteUrl == absoluteUrl))
.ForCondition(x => (_callsCount == null && x.Any(y => y.AbsoluteUrl == absoluteUrl)) || (_callsCount == x.Count(y => y.AbsoluteUrl == absoluteUrl)))
.FailWith(
"Expected {context:wiremockserver} to have been called at address matching the absolute url {0}{reason}, but didn't find it among the calls to {1}.",
_ => absoluteUrl, requests => requests.Select(request => request.AbsoluteUrl));
@@ -48,7 +48,7 @@ public class WireMockAssertions
"Expected {context:wiremockserver} to have been called at address matching the url {0}{reason}, but no calls were made.",
url)
.Then
.ForCondition(x => _callsCount == null && x.Any(y => y.Url == url) || _callsCount == x.Count(y => y.Url == url))
.ForCondition(x => (_callsCount == null && x.Any(y => y.Url == url)) || (_callsCount == x.Count(y => y.Url == url)))
.FailWith(
"Expected {context:wiremockserver} to have been called at address matching the url {0}{reason}, but didn't find it among the calls to {1}.",
_ => url, requests => requests.Select(request => request.Url));
@@ -67,7 +67,7 @@ public class WireMockAssertions
"Expected {context:wiremockserver} to have been called with proxy url {0}{reason}, but no calls were made.",
proxyUrl)
.Then
.ForCondition(x => _callsCount == null && x.Any(y => y.ProxyUrl == proxyUrl) || _callsCount == x.Count(y => y.ProxyUrl == proxyUrl))
.ForCondition(x => (_callsCount == null && x.Any(y => y.ProxyUrl == proxyUrl)) || (_callsCount == x.Count(y => y.ProxyUrl == proxyUrl)))
.FailWith(
"Expected {context:wiremockserver} to have been called with proxy url {0}{reason}, but didn't find it among the calls with {1}.",
_ => proxyUrl, requests => requests.Select(request => request.ProxyUrl));
@@ -86,7 +86,7 @@ public class WireMockAssertions
"Expected {context:wiremockserver} to have been called from client IP {0}{reason}, but no calls were made.",
clientIP)
.Then
.ForCondition(x => _callsCount == null && x.Any(y => y.ClientIP == clientIP) || _callsCount == x.Count(y => y.ClientIP == clientIP))
.ForCondition(x => (_callsCount == null && x.Any(y => y.ClientIP == clientIP)) || (_callsCount == x.Count(y => y.ClientIP == clientIP)))
.FailWith(
"Expected {context:wiremockserver} to have been called from client IP {0}{reason}, but didn't find it among the calls from IP(s) {1}.",
_ => clientIP, requests => requests.Select(request => request.ClientIP));
@@ -129,4 +129,59 @@ public class WireMockAssertions
return new AndConstraint<WireMockAssertions>(this);
}
[CustomAssertion]
public AndConstraint<WireMockAssertions> UsingConnect(string because = "", params object[] becauseArgs)
=> UsingMethod("CONNECT", because, becauseArgs);
[CustomAssertion]
public AndConstraint<WireMockAssertions> UsingDelete(string because = "", params object[] becauseArgs)
=> UsingMethod("DELETE", because, becauseArgs);
[CustomAssertion]
public AndConstraint<WireMockAssertions> UsingGet(string because = "", params object[] becauseArgs)
=> UsingMethod("GET", because, becauseArgs);
[CustomAssertion]
public AndConstraint<WireMockAssertions> UsingHead(string because = "", params object[] becauseArgs)
=> UsingMethod("HEAD", because, becauseArgs);
[CustomAssertion]
public AndConstraint<WireMockAssertions> UsingOptions(string because = "", params object[] becauseArgs)
=> UsingMethod("OPTIONS", because, becauseArgs);
[CustomAssertion]
public AndConstraint<WireMockAssertions> UsingPost(string because = "", params object[] becauseArgs)
=> UsingMethod("POST", because, becauseArgs);
[CustomAssertion]
public AndConstraint<WireMockAssertions> UsingPatch(string because = "", params object[] becauseArgs)
=> UsingMethod("PATCH", because, becauseArgs);
[CustomAssertion]
public AndConstraint<WireMockAssertions> UsingPut(string because = "", params object[] becauseArgs)
=> UsingMethod("PUT", because, becauseArgs);
[CustomAssertion]
public AndConstraint<WireMockAssertions> UsingTrace(string because = "", params object[] becauseArgs)
=> UsingMethod("TRACE", because, becauseArgs);
[CustomAssertion]
public AndConstraint<WireMockAssertions> UsingMethod(string method, string because = "", params object[] becauseArgs)
{
Execute.Assertion
.BecauseOf(because, becauseArgs)
.Given(() => _subject.LogEntries.Select(x => x.RequestMessage).ToList())
.ForCondition(requests => requests.Any())
.FailWith(
"Expected {context:wiremockserver} to have been called using method {0}{reason}, but no calls were made.",
method)
.Then
.ForCondition(x => (_callsCount == null && x.Any(y => y.Method == method)) || (_callsCount == x.Count(y => y.Method == method)))
.FailWith(
"Expected {context:wiremockserver} to have been called using method {0}{reason}, but didn't find it among the methods {1}.",
_ => method, requests => requests.Select(request => request.Method));
return new AndConstraint<WireMockAssertions>(this);
}
}

View File

@@ -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> Random = new(() => new Random(DateTime.UtcNow.Millisecond));
private readonly WireMockServerSettings _settings;
@@ -25,19 +28,26 @@ internal class WebhookSender
_settings = Guard.NotNull(settings);
}
public Task<HttpResponseMessage> SendAsync(HttpClient client, IWebhookRequest request, IRequestMessage originalRequestMessage, IResponseMessage originalResponseMessage)
public async Task<HttpResponseMessage> SendAsync(
HttpClient client,
IMapping mapping,
IWebhookRequest webhookRequest,
IRequestMessage originalRequestMessage,
IResponseMessage originalResponseMessage
)
{
Guard.NotNull(client);
Guard.NotNull(request);
Guard.NotNull(mapping);
Guard.NotNull(webhookRequest);
Guard.NotNull(originalRequestMessage);
Guard.NotNull(originalResponseMessage);
IBodyData? bodyData;
IDictionary<string, WireMockList<string>>? 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);
@@ -46,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(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())
@@ -75,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;
}
}

View File

@@ -112,6 +112,11 @@ public interface IMapping
/// </summary>
IWebhook[]? Webhooks { get; }
/// <summary>
/// Use Fire and Forget for the defined webhook(s). [Optional]
/// </summary>
public bool? UseWebhooksFireAndForget { get; set; }
/// <summary>
/// ProvideResponseAsync
/// </summary>

View File

@@ -15,14 +15,14 @@ public class Mapping : IMapping
/// <inheritdoc />
public Guid Guid { get; }
/// <inheritdoc />
public string? Title { get; }
/// <inheritdoc />
public string? Title { get; }
/// <inheritdoc />
public string? Description { get; }
/// <inheritdoc />
public string? Description { get; }
/// <inheritdoc />
public string? Path { get; set; }
/// <inheritdoc />
public string? Path { get; set; }
/// <inheritdoc />
public int Priority { get; }
@@ -63,6 +63,9 @@ public class Mapping : IMapping
/// <inheritdoc />
public IWebhook[]? Webhooks { get; }
/// <inheritdoc />
public bool? UseWebhooksFireAndForget { get; set; }
/// <inheritdoc />
public ITimeSettings? TimeSettings { get; }
@@ -82,6 +85,7 @@ public class Mapping : IMapping
/// <param name="nextState">The next state which will occur after the current mapping execution. [Optional]</param>
/// <param name="stateTimes">Only when the current state is executed this number, the next state which will occur. [Optional]</param>
/// <param name="webhooks">The Webhooks. [Optional]</param>
/// <param name="useWebhooksFireAndForget">Use Fire and Forget for the defined webhook(s). [Optional]</param>
/// <param name="timeSettings">The TimeSettings. [Optional]</param>
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,19 +117,20 @@ public class Mapping : IMapping
NextState = nextState;
StateTimes = stateTimes;
Webhooks = webhooks;
UseWebhooksFireAndForget = useWebhooksFireAndForget;
TimeSettings = timeSettings;
}
/// <inheritdoc cref="IMapping.ProvideResponseAsync" />
public Task<(IResponseMessage Message, IMapping? Mapping)> ProvideResponseAsync(IRequestMessage requestMessage)
{
return Provider.ProvideResponseAsync(requestMessage, Settings);
}
/// <inheritdoc cref="IMapping.ProvideResponseAsync" />
public Task<(IResponseMessage Message, IMapping? Mapping)> ProvideResponseAsync(IRequestMessage requestMessage)
{
return Provider.ProvideResponseAsync(this, requestMessage, Settings);
}
/// <inheritdoc cref="IMapping.GetRequestMatchResult" />
public IRequestMatchResult GetRequestMatchResult(IRequestMessage requestMessage, string? nextState)
{
var result = new RequestMatchResult();
/// <inheritdoc cref="IMapping.GetRequestMatchResult" />
public IRequestMatchResult GetRequestMatchResult(IRequestMessage requestMessage, string? nextState)
{
var result = new RequestMatchResult();
RequestMatcher.GetMatchingScore(requestMessage, result);

View File

@@ -1,8 +1,7 @@
using Stef.Validation;
using System;
using System.Collections.Generic;
using System.Linq;
using JetBrains.Annotations;
using Stef.Validation;
namespace WireMock.Matchers.Request;
@@ -13,12 +12,13 @@ namespace WireMock.Matchers.Request;
public class RequestMessageCookieMatcher : IRequestMatcher
{
private readonly MatchBehaviour _matchBehaviour;
private readonly bool _ignoreCase;
/// <summary>
/// The functions
/// </summary>
public Func<IDictionary<string, string>, bool>[] Funcs { get; }
public Func<IDictionary<string, string>, bool>[]? Funcs { get; }
/// <summary>
/// The name
@@ -28,7 +28,7 @@ public class RequestMessageCookieMatcher : IRequestMatcher
/// <value>
/// The matchers.
/// </value>
public IStringMatcher[] Matchers { get; }
public IStringMatcher[]? Matchers { get; }
/// <summary>
/// Initializes a new instance of the <see cref="RequestMessageCookieMatcher"/> class.
@@ -37,15 +37,12 @@ public class RequestMessageCookieMatcher : IRequestMatcher
/// <param name="pattern">The pattern.</param>
/// <param name="ignoreCase">Ignore the case from the pattern.</param>
/// <param name="matchBehaviour">The match behaviour.</param>
public RequestMessageCookieMatcher(MatchBehaviour matchBehaviour, [NotNull] string name, [NotNull] string pattern, bool ignoreCase)
public RequestMessageCookieMatcher(MatchBehaviour matchBehaviour, string name, string pattern, bool ignoreCase)
{
Guard.NotNull(name, nameof(name));
Guard.NotNull(pattern, nameof(pattern));
_matchBehaviour = matchBehaviour;
_ignoreCase = ignoreCase;
Name = name;
Matchers = new IStringMatcher[] { new WildcardMatcher(matchBehaviour, pattern, ignoreCase) };
Name = Guard.NotNull(name);
Matchers = new IStringMatcher[] { new WildcardMatcher(matchBehaviour, Guard.NotNull(pattern), ignoreCase) };
}
/// <summary>
@@ -55,10 +52,10 @@ public class RequestMessageCookieMatcher : IRequestMatcher
/// <param name="name">The name.</param>
/// <param name="patterns">The patterns.</param>
/// <param name="ignoreCase">Ignore the case from the pattern.</param>
public RequestMessageCookieMatcher(MatchBehaviour matchBehaviour, [NotNull] string name, bool ignoreCase, [NotNull] params string[] patterns) :
public RequestMessageCookieMatcher(MatchBehaviour matchBehaviour, string name, bool ignoreCase, params string[] patterns) :
this(matchBehaviour, name, ignoreCase, patterns.Select(pattern => new WildcardMatcher(matchBehaviour, pattern, ignoreCase)).Cast<IStringMatcher>().ToArray())
{
Guard.NotNull(patterns, nameof(patterns));
Guard.NotNull(patterns);
}
/// <summary>
@@ -68,14 +65,11 @@ public class RequestMessageCookieMatcher : IRequestMatcher
/// <param name="name">The name.</param>
/// <param name="matchers">The matchers.</param>
/// <param name="ignoreCase">Ignore the case from the pattern.</param>
public RequestMessageCookieMatcher(MatchBehaviour matchBehaviour, [NotNull] string name, bool ignoreCase, [NotNull] params IStringMatcher[] matchers)
public RequestMessageCookieMatcher(MatchBehaviour matchBehaviour, string name, bool ignoreCase, params IStringMatcher[] matchers)
{
Guard.NotNull(name, nameof(name));
Guard.NotNull(matchers, nameof(matchers));
_matchBehaviour = matchBehaviour;
Name = name;
Matchers = matchers;
Name = Guard.NotNull(name);
Matchers = Guard.NotNull(matchers);
_ignoreCase = ignoreCase;
}
@@ -83,11 +77,12 @@ public class RequestMessageCookieMatcher : IRequestMatcher
/// Initializes a new instance of the <see cref="RequestMessageCookieMatcher"/> class.
/// </summary>
/// <param name="funcs">The funcs.</param>
public RequestMessageCookieMatcher([NotNull] params Func<IDictionary<string, string>, bool>[] funcs)
public RequestMessageCookieMatcher(params Func<IDictionary<string, string>, bool>[] funcs)
{
Guard.NotNull(funcs, nameof(funcs));
Guard.NotNull(funcs);
Funcs = funcs;
Name = string.Empty; // Not used when Func, but set to a non-null valid value.
}
/// <inheritdoc />

View File

@@ -11,7 +11,10 @@ namespace WireMock.Matchers.Request;
/// </summary>
public class RequestMessageParamMatcher : IRequestMatcher
{
private readonly MatchBehaviour _matchBehaviour;
/// <summary>
/// MatchBehaviour
/// </summary>
public MatchBehaviour MatchBehaviour { get; }
/// <summary>
/// The funcs
@@ -21,7 +24,7 @@ public class RequestMessageParamMatcher : IRequestMatcher
/// <summary>
/// The key
/// </summary>
public string? Key { get; }
public string Key { get; } = string.Empty;
/// <summary>
/// Defines if the key should be matched using case-ignore.
@@ -63,7 +66,7 @@ public class RequestMessageParamMatcher : IRequestMatcher
/// <param name="matchers">The matchers.</param>
public RequestMessageParamMatcher(MatchBehaviour matchBehaviour, string key, bool ignoreCase, IStringMatcher[]? matchers)
{
_matchBehaviour = matchBehaviour;
MatchBehaviour = matchBehaviour;
Key = Guard.NotNull(key);
IgnoreCase = ignoreCase;
Matchers = matchers;
@@ -81,7 +84,7 @@ public class RequestMessageParamMatcher : IRequestMatcher
/// <inheritdoc />
public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult)
{
double score = MatchBehaviourHelper.Convert(_matchBehaviour, IsMatch(requestMessage));
double score = MatchBehaviourHelper.Convert(MatchBehaviour, IsMatch(requestMessage));
return requestMatchResult.AddScore(GetType(), score);
}

View File

@@ -1,11 +1,10 @@
namespace WireMock.Models
namespace WireMock.Models;
/// <summary>
/// Webhook
/// </summary>
public class Webhook : IWebhook
{
/// <summary>
/// Webhook
/// </summary>
public class Webhook : IWebhook
{
/// <inheritdoc cref="IWebhook.Request"/>
public IWebhookRequest Request { get; set; }
}
/// <inheritdoc />
public IWebhookRequest Request { get; set; } = null!;
}

View File

@@ -2,32 +2,40 @@ using System.Collections.Generic;
using WireMock.Types;
using WireMock.Util;
namespace WireMock.Models
namespace WireMock.Models;
/// <summary>
/// WebhookRequest
/// </summary>
public class WebhookRequest : IWebhookRequest
{
/// <summary>
/// WebhookRequest
/// </summary>
public class WebhookRequest : IWebhookRequest
{
/// <inheritdoc cref="IWebhookRequest.Url"/>
public string Url { get; set; }
/// <inheritdoc />
public string Url { get; set; } = null!;
/// <inheritdoc cref="IWebhookRequest.Method"/>
public string Method { get; set; }
/// <inheritdoc />
public string Method { get; set; } = null!;
/// <inheritdoc cref="IWebhookRequest.Headers"/>
public IDictionary<string, WireMockList<string>>? Headers { get; set; }
/// <inheritdoc />
public IDictionary<string, WireMockList<string>>? Headers { get; set; }
/// <inheritdoc cref="IWebhookRequest.BodyData"/>
public IBodyData? BodyData { get; set; }
/// <inheritdoc />
public IBodyData? BodyData { get; set; }
/// <inheritdoc cref="IWebhookRequest.UseTransformer"/>
public bool? UseTransformer { get; set; }
/// <inheritdoc />
public bool? UseTransformer { get; set; }
/// <inheritdoc cref="IWebhookRequest.TransformerType"/>
public TransformerType TransformerType { get; set; }
/// <inheritdoc />
public TransformerType TransformerType { get; set; }
/// <inheritdoc cref="IWebhookRequest.TransformerReplaceNodeOptions"/>
public ReplaceNodeOptions TransformerReplaceNodeOptions { get; set; }
}
/// <inheritdoc />
public ReplaceNodeOptions TransformerReplaceNodeOptions { get; set; }
/// <inheritdoc />
public int? Delay { get; set; }
/// <inheritdoc />
public int? MinimumRandomDelay { get; set; }
/// <inheritdoc />
public int? MaximumRandomDelay { get; set; }
}

View File

@@ -1,12 +1,15 @@
namespace WireMock.Owin;
/// <summary>
/// https://en.wikipedia.org/wiki/Uniform_Resource_Identifier
/// </summary>
internal struct HostUrlDetails
{
public bool IsHttps { get; set; }
public string Url { get; set; }
public string Protocol { get; set; }
public string Scheme { get; set; }
public string Host { get; set; }

View File

@@ -1,34 +1,49 @@
using System.Collections.Generic;
using WireMock.Types;
using WireMock.Util;
namespace WireMock.Owin;
internal class HostUrlOptions
{
private const string LOCALHOST = "localhost";
private const string Localhost = "localhost";
public ICollection<string>? Urls { get; set; }
public int? Port { get; set; }
public bool UseSSL { get; set; }
public int? HttpsPort { get; set; }
public ICollection<HostUrlDetails> GetDetails()
public HostingScheme HostingScheme { get; set; }
public IReadOnlyList<HostUrlDetails> GetDetails()
{
var list = new List<HostUrlDetails>();
if (Urls == null)
{
int port = Port > 0 ? Port.Value : FindFreeTcpPort();
string protocol = UseSSL ? "https" : "http";
list.Add(new HostUrlDetails { IsHttps = UseSSL, Url = $"{protocol}://{LOCALHOST}:{port}", Protocol = protocol, Host = LOCALHOST, Port = port });
if (HostingScheme is HostingScheme.Http or HostingScheme.Https)
{
var port = Port > 0 ? Port.Value : FindFreeTcpPort();
var scheme = HostingScheme == HostingScheme.Https ? "https" : "http";
list.Add(new HostUrlDetails { IsHttps = HostingScheme == HostingScheme.Https, Url = $"{scheme}://{Localhost}:{port}", Scheme = scheme, Host = Localhost, Port = port });
}
if (HostingScheme == HostingScheme.HttpAndHttps)
{
var httpPort = Port > 0 ? Port.Value : FindFreeTcpPort();
list.Add(new HostUrlDetails { IsHttps = false, Url = $"http://{Localhost}:{httpPort}", Scheme = "http", Host = Localhost, Port = httpPort });
var httpsPort = FindFreeTcpPort(); // In this scenario, always get a free port for https.
list.Add(new HostUrlDetails { IsHttps = true, Url = $"https://{Localhost}:{httpsPort}", Scheme = "https", Host = Localhost, Port = httpsPort });
}
}
else
{
foreach (string url in Urls)
{
if (PortUtils.TryExtract(url, out bool isHttps, out var protocol, out var host, out int port))
if (PortUtils.TryExtract(url, out var isHttps, out var protocol, out var host, out var port))
{
list.Add(new HostUrlDetails { IsHttps = isHttps, Url = url, Protocol = protocol, Host = host, Port = port });
list.Add(new HostUrlDetails { IsHttps = isHttps, Url = url, Scheme = protocol, Host = host, Port = port });
}
}
}

View File

@@ -4,12 +4,12 @@ using WireMock.Handlers;
using WireMock.Logging;
using WireMock.Matchers;
using WireMock.Util;
using WireMock.Types;
#if !USE_ASPNETCORE
using Owin;
#else
using IAppBuilder = Microsoft.AspNetCore.Builder.IApplicationBuilder;
using Microsoft.Extensions.DependencyInjection;
using WireMock.Types;
#endif
namespace WireMock.Owin;

View File

@@ -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;
@@ -26,7 +26,7 @@ namespace WireMock.Owin
{
internal class WireMockMiddleware : OwinMiddleware
{
private readonly object _lock = new object();
private readonly object _lock = new();
private static readonly Task CompletedTask = Task.FromResult(false);
private readonly IWireMockMiddlewareOptions _options;
private readonly IOwinRequestMapper _requestMapper;
@@ -108,10 +108,10 @@ namespace WireMock.Owin
logRequest = targetMapping.LogMapping;
if (targetMapping.IsAdminInterface && _options.AuthenticationMatcher != null)
if (targetMapping.IsAdminInterface && _options.AuthenticationMatcher != null && request.Headers != null)
{
bool present = request.Headers.TryGetValue(HttpKnownHeaderNames.Authorization, out WireMockList<string> authorization);
if (!present || _options.AuthenticationMatcher.IsMatch(authorization.ToString()) < MatchScores.Perfect)
if (!present || _options.AuthenticationMatcher.IsMatch(authorization!.ToString()) < MatchScores.Perfect)
{
_options.Logger.Error("HttpStatusCode set to 401");
response = ResponseMessageBuilder.Create(null, HttpStatusCode.Unauthorized);
@@ -201,20 +201,46 @@ namespace WireMock.Owin
private async Task SendToWebhooksAsync(IMapping mapping, IRequestMessage request, IResponseMessage response)
{
var tasks = new List<Func<Task>>();
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.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)

View File

@@ -1,16 +1,10 @@
using Stef.Validation;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using Stef.Validation;
using WireMock.Constants;
using WireMock.Http;
using WireMock.Matchers;
using WireMock.RequestBuilders;
using WireMock.ResponseBuilders;
using WireMock.Serialization;
using WireMock.Settings;
using WireMock.Types;
using WireMock.Util;
namespace WireMock.Proxy;
@@ -18,13 +12,16 @@ namespace WireMock.Proxy;
internal class ProxyHelper
{
private readonly WireMockServerSettings _settings;
private readonly ProxyMappingConverter _proxyMappingConverter;
public ProxyHelper(WireMockServerSettings settings)
{
_settings = Guard.NotNull(settings);
_proxyMappingConverter = new ProxyMappingConverter(settings, new GuidUtils());
}
public async Task<(IResponseMessage Message, IMapping? Mapping)> SendAsync(
IMapping? mapping,
ProxyAndRecordSettings proxyAndRecordSettings,
HttpClient client,
IRequestMessage requestMessage,
@@ -49,77 +46,13 @@ internal class ProxyHelper
var responseMessage = await HttpResponseMessageHelper.CreateAsync(httpResponseMessage, requiredUri, originalUri, deserializeJson, decompressGzipAndDeflate).ConfigureAwait(false);
IMapping? mapping = null;
IMapping? newMapping = null;
if (HttpStatusRangeParser.IsMatch(proxyAndRecordSettings.SaveMappingForStatusCodePattern, responseMessage.StatusCode) &&
(proxyAndRecordSettings.SaveMapping || proxyAndRecordSettings.SaveMappingToFile))
{
mapping = ToMapping(proxyAndRecordSettings, requestMessage, responseMessage);
newMapping = _proxyMappingConverter.ToMapping(mapping, proxyAndRecordSettings, requestMessage, responseMessage);
}
return (responseMessage, mapping);
}
private IMapping ToMapping(ProxyAndRecordSettings proxyAndRecordSettings, IRequestMessage requestMessage, ResponseMessage responseMessage)
{
var excludedHeaders = proxyAndRecordSettings.ExcludedHeaders ?? new string[] { };
var excludedCookies = proxyAndRecordSettings.ExcludedCookies ?? new string[] { };
var request = Request.Create();
request.WithPath(requestMessage.Path);
request.UsingMethod(requestMessage.Method);
requestMessage.Query?.Loop((key, value) => request.WithParam(key, false, value.ToArray()));
requestMessage.Cookies?.Loop((key, value) =>
{
if (!excludedCookies.Contains(key, StringComparer.OrdinalIgnoreCase))
{
request.WithCookie(key, value);
}
});
var allExcludedHeaders = new List<string>(excludedHeaders) { "Cookie" };
requestMessage.Headers?.Loop((key, value) =>
{
if (!allExcludedHeaders.Contains(key, StringComparer.OrdinalIgnoreCase))
{
request.WithHeader(key, value.ToArray());
}
});
bool throwExceptionWhenMatcherFails = _settings.ThrowExceptionWhenMatcherFails == true;
switch (requestMessage.BodyData?.DetectedBodyType)
{
case BodyType.Json:
request.WithBody(new JsonMatcher(MatchBehaviour.AcceptOnMatch, requestMessage.BodyData.BodyAsJson!, true, throwExceptionWhenMatcherFails));
break;
case BodyType.String:
request.WithBody(new ExactMatcher(MatchBehaviour.AcceptOnMatch, throwExceptionWhenMatcherFails, MatchOperator.Or, requestMessage.BodyData.BodyAsString));
break;
case BodyType.Bytes:
request.WithBody(new ExactObjectMatcher(MatchBehaviour.AcceptOnMatch, requestMessage.BodyData.BodyAsBytes, throwExceptionWhenMatcherFails));
break;
}
var response = Response.Create(responseMessage);
return new Mapping
(
guid: Guid.NewGuid(),
title: $"Proxy Mapping for {requestMessage.Method} {requestMessage.Path}",
description: string.Empty,
path: null,
settings: _settings,
request,
response,
priority: WireMockConstants.ProxyPriority, // This was 0
scenario: null,
executionConditionState: null,
nextState: null,
stateTimes: null,
webhooks: null,
timeSettings: null
);
return (responseMessage, newMapping);
}
}

View File

@@ -20,7 +20,7 @@ namespace WireMock.RequestBuilders
/// <inheritdoc cref="IParamsRequestBuilder.WithParam(string, bool, MatchBehaviour)"/>
public IRequestBuilder WithParam(string key, bool ignoreCase, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
{
Guard.NotNull(key, nameof(key));
Guard.NotNull(key);
_requestMatchers.Add(new RequestMessageParamMatcher(matchBehaviour, key, ignoreCase));
return this;

View File

@@ -244,7 +244,7 @@ public partial class Response : IResponseBuilder
}
/// <inheritdoc />
public async Task<(IResponseMessage Message, IMapping? Mapping)> ProvideResponseAsync(IRequestMessage requestMessage, WireMockServerSettings settings)
public async Task<(IResponseMessage Message, IMapping? Mapping)> ProvideResponseAsync(IMapping mapping, IRequestMessage requestMessage, WireMockServerSettings settings)
{
Guard.NotNull(requestMessage);
Guard.NotNull(settings);
@@ -271,6 +271,7 @@ public partial class Response : IResponseBuilder
var proxyHelper = new ProxyHelper(settings);
return await proxyHelper.SendAsync(
mapping,
ProxyAndRecordSettings,
_httpClientForProxy,
requestMessage,
@@ -327,7 +328,7 @@ public partial class Response : IResponseBuilder
throw new NotImplementedException($"TransformerType '{TransformerType}' is not supported.");
}
return (responseMessageTransformer.Transform(requestMessage, responseMessage, UseTransformerForBodyAsFile, TransformerReplaceNodeOptions), null);
return (responseMessageTransformer.Transform(mapping, requestMessage, responseMessage, UseTransformerForBodyAsFile, TransformerReplaceNodeOptions), null);
}
if (!UseTransformer && ResponseMessage.BodyData?.BodyAsFileIsCached == true)

View File

@@ -39,7 +39,7 @@ public class ResponseMessage : IResponseMessage
public void AddHeader(string name, string value)
{
Headers ??= new Dictionary<string, WireMockList<string>>();
Headers.Add(name, new WireMockList<string>(value));
Headers.Add(name, value);
}
/// <inheritdoc cref="IResponseMessage.AddHeader(string, string[])" />
@@ -52,6 +52,6 @@ public class ResponseMessage : IResponseMessage
? values.Union(existingValues).ToArray()
: values;
Headers[name] = new WireMockList<string>(newHeaderValues);
Headers[name] = newHeaderValues;
}
}

View File

@@ -13,7 +13,7 @@ internal class DynamicAsyncResponseProvider : IResponseProvider
_responseMessageFunc = responseMessageFunc;
}
public async Task<(IResponseMessage Message, IMapping? Mapping)> ProvideResponseAsync(IRequestMessage requestMessage, WireMockServerSettings settings)
public async Task<(IResponseMessage Message, IMapping? Mapping)> ProvideResponseAsync(IMapping mapping, IRequestMessage requestMessage, WireMockServerSettings settings)
{
return (await _responseMessageFunc(requestMessage).ConfigureAwait(false), null);
}

View File

@@ -13,7 +13,7 @@ internal class DynamicResponseProvider : IResponseProvider
_responseMessageFunc = responseMessageFunc;
}
public Task<(IResponseMessage Message, IMapping? Mapping)> ProvideResponseAsync(IRequestMessage requestMessage, WireMockServerSettings settings)
public Task<(IResponseMessage Message, IMapping? Mapping)> ProvideResponseAsync(IMapping mapping, IRequestMessage requestMessage, WireMockServerSettings settings)
{
(IResponseMessage responseMessage, IMapping? mapping) result = (_responseMessageFunc(requestMessage), null);
return Task.FromResult(result);

View File

@@ -13,8 +13,9 @@ public interface IResponseProvider
/// <summary>
/// The provide response.
/// </summary>
/// <param name="mapping">The used mapping.</param>
/// <param name="requestMessage">The request.</param>
/// <param name="settings">The WireMockServerSettings.</param>
/// <returns>The <see cref="ResponseMessage"/> including a new (optional) <see cref="IMapping"/>.</returns>
Task<(IResponseMessage Message, IMapping? Mapping)> ProvideResponseAsync(IRequestMessage requestMessage, WireMockServerSettings settings);
Task<(IResponseMessage Message, IMapping? Mapping)> ProvideResponseAsync(IMapping mapping, IRequestMessage requestMessage, WireMockServerSettings settings);
}

View File

@@ -15,7 +15,7 @@ internal class ProxyAsyncResponseProvider : IResponseProvider
_settings = settings;
}
public async Task<(IResponseMessage Message, IMapping? Mapping)> ProvideResponseAsync(IRequestMessage requestMessage, WireMockServerSettings settings)
public async Task<(IResponseMessage Message, IMapping? Mapping)> ProvideResponseAsync(IMapping mapping, IRequestMessage requestMessage, WireMockServerSettings settings)
{
return (await _responseMessageFunc(requestMessage, _settings).ConfigureAwait(false), null);
}

View File

@@ -1,33 +1,32 @@
namespace WireMock
namespace WireMock;
/// <summary>
/// The ScenarioState
/// </summary>
public class ScenarioState
{
/// <summary>
/// The ScenarioState
/// Gets or sets the Name (from the Scenario).
/// </summary>
public class ScenarioState
{
/// <summary>
/// Gets or sets the Name (from the Scenario).
/// </summary>
public string Name { get; set; }
public string? Name { get; set; }
/// <summary>
/// Gets or sets the NextState.
/// </summary>
public string NextState { get; set; }
/// <summary>
/// Gets or sets the NextState.
/// </summary>
public string? NextState { get; set; }
/// <summary>
/// Gets or sets a value indicating whether this <see cref="ScenarioState"/> is started.
/// </summary>
public bool Started { get; set; }
/// <summary>
/// Gets or sets a value indicating whether this <see cref="ScenarioState"/> is started.
/// </summary>
public bool Started { get; set; }
/// <summary>
/// Gets or sets a value indicating whether this <see cref="ScenarioState"/> is finished.
/// </summary>
public bool Finished { get; set; }
/// <summary>
/// Gets or sets a value indicating whether this <see cref="ScenarioState"/> is finished.
/// </summary>
public bool Finished { get; set; }
/// <summary>
/// Gets or sets the state counter.
/// </summary>
public int Counter { get; set; }
}
/// <summary>
/// Gets or sets the state counter.
/// </summary>
public int Counter { get; set; }
}

View File

@@ -20,7 +20,7 @@ internal class MappingConverter
public MappingConverter(MatcherMapper mapper)
{
_mapper = Guard.NotNull(mapper, nameof(mapper));
_mapper = Guard.NotNull(mapper);
}
public MappingModel ToMappingModel(IMapping mapping)
@@ -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);
}
@@ -250,8 +251,15 @@ internal class MappingConverter
var newDictionary = new Dictionary<string, object>();
foreach (var entry in dictionary)
{
object value = entry.Value.Count == 1 ? entry.Value.ToString() : entry.Value;
newDictionary.Add(entry.Key, value);
// ReSharper disable once ConvertIfStatementToConditionalTernaryExpression
if (entry.Value.Count == 1)
{
newDictionary.Add(entry.Key, entry.Value.ToString());
}
else
{
newDictionary.Add(entry.Key, entry.Value);
}
}
return newDictionary;

View File

@@ -0,0 +1,181 @@
using Stef.Validation;
using System;
using System.Collections.Generic;
using System.Linq;
using WireMock.Constants;
using WireMock.Matchers;
using WireMock.Matchers.Request;
using WireMock.RequestBuilders;
using WireMock.ResponseBuilders;
using WireMock.Settings;
using WireMock.Types;
using WireMock.Util;
namespace WireMock.Serialization;
internal class ProxyMappingConverter
{
private readonly WireMockServerSettings _settings;
private readonly IGuidUtils _guidUtils;
public ProxyMappingConverter(WireMockServerSettings settings, IGuidUtils guidUtils)
{
_settings = Guard.NotNull(settings);
_guidUtils = Guard.NotNull(guidUtils);
}
public IMapping ToMapping(IMapping? mapping, ProxyAndRecordSettings proxyAndRecordSettings, IRequestMessage requestMessage, ResponseMessage responseMessage)
{
var request = (Request?)mapping?.RequestMatcher;
var clientIPMatcher = request?.GetRequestMessageMatcher<RequestMessageClientIPMatcher>();
var pathMatcher = request?.GetRequestMessageMatcher<RequestMessagePathMatcher>();
var headerMatchers = request?.GetRequestMessageMatchers<RequestMessageHeaderMatcher>();
var cookieMatchers = request?.GetRequestMessageMatchers<RequestMessageCookieMatcher>();
var paramMatchers = request?.GetRequestMessageMatchers<RequestMessageParamMatcher>();
var methodMatcher = request?.GetRequestMessageMatcher<RequestMessageMethodMatcher>();
var bodyMatcher = request?.GetRequestMessageMatcher<RequestMessageBodyMatcher>();
var useDefinedRequestMatchers = proxyAndRecordSettings.UseDefinedRequestMatchers;
var excludedHeaders = new List<string>(proxyAndRecordSettings.ExcludedHeaders ?? new string[] { }) { "Cookie" };
var excludedCookies = proxyAndRecordSettings.ExcludedCookies ?? new string[] { };
var newRequest = Request.Create();
// ClientIP
if (useDefinedRequestMatchers && clientIPMatcher?.Matchers is not null)
{
newRequest.WithClientIP(clientIPMatcher.MatchOperator, clientIPMatcher.Matchers.ToArray());
}
// Path
if (useDefinedRequestMatchers && pathMatcher?.Matchers is not null)
{
newRequest.WithPath(pathMatcher.MatchOperator, pathMatcher.Matchers.ToArray());
}
else
{
newRequest.WithPath(requestMessage.Path);
}
// Method
if (useDefinedRequestMatchers && methodMatcher is not null)
{
newRequest.UsingMethod(methodMatcher.Methods);
}
else
{
newRequest.UsingMethod(requestMessage.Method);
}
// QueryParams
if (useDefinedRequestMatchers && paramMatchers is not null)
{
foreach (var paramMatcher in paramMatchers)
{
newRequest.WithParam(paramMatcher.Key, paramMatcher.MatchBehaviour, paramMatcher.Matchers!.ToArray());
}
}
else
{
requestMessage.Query?.Loop((key, value) => newRequest.WithParam(key, false, value.ToArray()));
}
// Cookies
if (useDefinedRequestMatchers && cookieMatchers is not null)
{
foreach (var cookieMatcher in cookieMatchers.Where(hm => hm.Matchers is not null))
{
if (!excludedCookies.Contains(cookieMatcher.Name, StringComparer.OrdinalIgnoreCase))
{
newRequest.WithCookie(cookieMatcher.Name, cookieMatcher.Matchers!);
}
}
}
else
{
requestMessage.Cookies?.Loop((key, value) =>
{
if (!excludedCookies.Contains(key, StringComparer.OrdinalIgnoreCase))
{
newRequest.WithCookie(key, value);
}
});
}
// Headers
if (useDefinedRequestMatchers && headerMatchers is not null)
{
foreach (var headerMatcher in headerMatchers.Where(hm => hm.Matchers is not null))
{
if (!excludedHeaders.Contains(headerMatcher.Name, StringComparer.OrdinalIgnoreCase))
{
newRequest.WithHeader(headerMatcher.Name, headerMatcher.Matchers!);
}
}
}
else
{
requestMessage.Headers?.Loop((key, value) =>
{
if (!excludedHeaders.Contains(key, StringComparer.OrdinalIgnoreCase))
{
newRequest.WithHeader(key, value.ToArray());
}
});
}
// Body
bool throwExceptionWhenMatcherFails = _settings.ThrowExceptionWhenMatcherFails == true;
if (useDefinedRequestMatchers && bodyMatcher?.Matchers is not null)
{
newRequest.WithBody(bodyMatcher.Matchers);
}
else
{
switch (requestMessage.BodyData?.DetectedBodyType)
{
case BodyType.Json:
newRequest.WithBody(new JsonMatcher(MatchBehaviour.AcceptOnMatch, requestMessage.BodyData.BodyAsJson!, true, throwExceptionWhenMatcherFails));
break;
case BodyType.String:
newRequest.WithBody(new ExactMatcher(MatchBehaviour.AcceptOnMatch, throwExceptionWhenMatcherFails, MatchOperator.Or, requestMessage.BodyData.BodyAsString));
break;
case BodyType.Bytes:
newRequest.WithBody(new ExactObjectMatcher(MatchBehaviour.AcceptOnMatch, requestMessage.BodyData.BodyAsBytes, throwExceptionWhenMatcherFails));
break;
}
}
// Title
var title = useDefinedRequestMatchers && !string.IsNullOrEmpty(mapping?.Title) ?
mapping!.Title :
$"Proxy Mapping for {requestMessage.Method} {requestMessage.Path}";
// Description
var description = useDefinedRequestMatchers && !string.IsNullOrEmpty(mapping?.Description) ?
mapping!.Description :
$"Proxy Mapping for {requestMessage.Method} {requestMessage.Path}";
return new Mapping
(
guid: _guidUtils.NewGuid(),
title: title,
description: description,
path: null,
settings: _settings,
requestMatcher: newRequest,
provider: Response.Create(responseMessage),
priority: WireMockConstants.ProxyPriority, // This was 0
scenario: null,
executionConditionState: null,
nextState: null,
stateTimes: null,
webhooks: null,
useWebhooksFireAndForget: null,
timeSettings: null
);
}
}

View File

@@ -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<string>(x.Value)) ?? new Dictionary<string, WireMockList<string>>()
}
};
@@ -27,6 +30,7 @@ internal static class WebhookMapper
if (model.Request.UseTransformer == true)
{
webhook.Request.UseTransformer = true;
if (!Enum.TryParse<TransformerType>(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,
}
};

View File

@@ -123,6 +123,13 @@ namespace WireMock.Server
/// <returns>The <see cref="IRespondWithAProvider"/>.</returns>
IRespondWithAProvider WithWebhook(params IWebhook[] webhooks);
/// <summary>
/// Support FireAndForget for any configured Webhooks
/// </summary>
/// <param name="UseWebhooksFireAndForget"></param>
/// <returns></returns>
IRespondWithAProvider WithWebhookFireAndForget(bool UseWebhooksFireAndForget);
/// <summary>
/// Add a Webhook to call after the response has been generated.
/// </summary>

View File

@@ -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
/// <param name="provider">The provider.</param>
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);
}
/// <inheritdoc />
@@ -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,

View File

@@ -236,6 +236,7 @@ public partial class WireMockServer
var proxyHelper = new ProxyHelper(settings);
var (responseMessage, mapping) = await proxyHelper.SendAsync(
null,
_settings.ProxyAndRecordSettings!,
_httpClientForProxy!,
requestMessage,

View File

@@ -198,7 +198,7 @@ public partial class WireMockServer
{
foreach (var cookieModel in requestModel.Cookies.Where(c => c.Matchers != null))
{
requestBuilder = requestBuilder.WithCookie(
requestBuilder = requestBuilder.WithCookie(
cookieModel.Name,
cookieModel.IgnoreCase == true,
cookieModel.RejectOnMatch == true ? MatchBehaviour.RejectOnMatch : MatchBehaviour.AcceptOnMatch,

View File

@@ -21,6 +21,7 @@ using WireMock.RequestBuilders;
using WireMock.ResponseProviders;
using WireMock.Serialization;
using WireMock.Settings;
using WireMock.Types;
namespace WireMock.Server;
@@ -48,7 +49,7 @@ public partial class WireMockServer : IWireMockServer
/// <inheritdoc />
[PublicAPI]
public int Port => Ports?.FirstOrDefault() ?? default(int);
public int Port => Ports?.FirstOrDefault() ?? default;
/// <inheritdoc />
[PublicAPI]
@@ -269,11 +270,22 @@ public partial class WireMockServer : IWireMockServer
}
else
{
urlOptions = new HostUrlOptions
if (settings.HostingScheme is not null)
{
UseSSL = settings.UseSSL == true,
Port = settings.Port
};
urlOptions = new HostUrlOptions
{
HostingScheme = settings.HostingScheme.Value,
Port = settings.Port
};
}
else
{
urlOptions = new HostUrlOptions
{
HostingScheme = settings.UseSSL == true ? HostingScheme.Https : HostingScheme.Http,
Port = settings.Port
};
}
}
_options.FileSystemHandler = _settings.FileSystemHandler;

View File

@@ -49,4 +49,13 @@ public class ProxyAndRecordSettings : HttpClientSettings
/// </summary>
//[PublicAPI]
//public bool PreferProxyMapping { get; set; }
/// <summary>
/// When SaveMapping is set to <c>true</c>, this setting can be used to control the behavior of the generated request matchers for the new mapping.
/// - <c>false</c>, the default matchers will be used.
/// - <c>true</c>, the defined mappings in the request wil be used for the new mapping.
///
/// Default value is false.
/// </summary>
public bool UseDefinedRequestMatchers { get; set; }
}

View File

@@ -94,6 +94,26 @@ internal class SimpleCommandLineParser
}, defaultValue);
}
public TEnum? GetEnumValue<TEnum>(string name)
where TEnum : struct
{
return GetValue(name, values =>
{
var value = values.FirstOrDefault();
return Enum.TryParse<TEnum>(value, true, out var enumValue) ? enumValue : (TEnum?)null;
});
}
public TEnum GetEnumValue<TEnum>(string name, TEnum defaultValue)
where TEnum : struct
{
return GetValue(name, values =>
{
var value = values.FirstOrDefault();
return Enum.TryParse<TEnum>(value, true, out var enumValue) ? enumValue : defaultValue;
}, defaultValue);
}
public string GetStringValue(string name, string defaultValue)
{
return GetValue(name, values => values.FirstOrDefault() ?? defaultValue, defaultValue);

View File

@@ -9,6 +9,7 @@ using WireMock.Handlers;
using WireMock.Logging;
using WireMock.Matchers;
using WireMock.RegularExpressions;
using WireMock.Types;
#if USE_ASPNETCORE
using Microsoft.Extensions.DependencyInjection;
using WireMock.Types;
@@ -22,7 +23,7 @@ namespace WireMock.Settings
public class WireMockServerSettings
{
/// <summary>
/// Gets or sets the port.
/// Gets or sets the http port.
/// </summary>
[PublicAPI]
public int? Port { get; set; }
@@ -34,6 +35,12 @@ namespace WireMock.Settings
[PublicAPI]
public bool? UseSSL { get; set; }
/// <summary>
/// Defines on which scheme (http/https) to host. (This overrides the <c>UseSSL</c> value).
/// </summary>
[PublicAPI]
public HostingScheme? HostingScheme { get; set; }
/// <summary>
/// Gets or sets whether to start admin interface.
/// </summary>

View File

@@ -21,7 +21,7 @@ public static class WireMockServerSettingsParser
[PublicAPI]
public static bool TryParseArguments(string[] args, [NotNullWhen(true)] out WireMockServerSettings? settings, IWireMockLogger? logger = null)
{
Guard.HasNoNulls(args, nameof(args));
Guard.HasNoNulls(args);
var parser = new SimpleCommandLineParser();
parser.Parse(args);
@@ -54,22 +54,18 @@ public static class WireMockServerSettingsParser
UseRegexExtended = parser.GetBoolValue(nameof(WireMockServerSettings.UseRegexExtended), true),
WatchStaticMappings = parser.GetBoolValue("WatchStaticMappings"),
WatchStaticMappingsInSubdirectories = parser.GetBoolValue("WatchStaticMappingsInSubdirectories"),
HostingScheme = parser.GetEnumValue<HostingScheme>(nameof(WireMockServerSettings.HostingScheme))
};
#if USE_ASPNETCORE
settings.CorsPolicyOptions = parser.GetValue(nameof(WireMockServerSettings.CorsPolicyOptions), values =>
{
var value = string.Join(string.Empty, values);
return Enum.TryParse<CorsPolicyOptions>(value, true, out var corsPolicyOptions) ? corsPolicyOptions : CorsPolicyOptions.None;
});
settings.CorsPolicyOptions = parser.GetEnumValue(nameof(WireMockServerSettings.CorsPolicyOptions), CorsPolicyOptions.None);
#endif
if (logger != null)
{
settings.Logger = logger;
}
if (parser.GetStringValue("WireMockLogger") == "WireMockConsoleLogger")
else if (parser.GetStringValue("WireMockLogger") == "WireMockConsoleLogger")
{
settings.Logger = new WireMockConsoleLogger();
}
@@ -78,7 +74,7 @@ public static class WireMockServerSettingsParser
{
settings.Port = parser.GetIntValue(nameof(WireMockServerSettings.Port));
}
else
else if (settings.HostingScheme is null)
{
settings.Urls = parser.GetValues("Urls", new[] { "http://*:9091/" });
}
@@ -96,7 +92,8 @@ public static class WireMockServerSettingsParser
SaveMapping = parser.GetBoolValue("SaveMapping"),
SaveMappingForStatusCodePattern = parser.GetStringValue("SaveMappingForStatusCodePattern", "*"),
SaveMappingToFile = parser.GetBoolValue("SaveMappingToFile"),
Url = proxyUrl
UseDefinedRequestMatchers = parser.GetBoolValue(nameof(ProxyAndRecordSettings.UseDefinedRequestMatchers)),
Url = proxyUrl!
};
string? proxyAddress = parser.GetStringValue("WebProxyAddress");
@@ -104,7 +101,7 @@ public static class WireMockServerSettingsParser
{
settings.ProxyAndRecordSettings.WebProxySettings = new WebProxySettings
{
Address = proxyAddress,
Address = proxyAddress!,
UserName = parser.GetStringValue("WebProxyUserName"),
Password = parser.GetStringValue("WebProxyPassword")
};

View File

@@ -6,7 +6,7 @@ namespace WireMock.Transformers;
interface ITransformer
{
ResponseMessage Transform(IRequestMessage requestMessage, IResponseMessage original, bool useTransformerForBodyAsFile, ReplaceNodeOptions options);
ResponseMessage Transform(IMapping mapping, IRequestMessage requestMessage, IResponseMessage original, bool useTransformerForBodyAsFile, ReplaceNodeOptions options);
(IBodyData? BodyData, IDictionary<string, WireMockList<string>>? Headers) Transform(IRequestMessage originalRequestMessage, IResponseMessage originalResponseMessage, IBodyData? bodyData, IDictionary<string, WireMockList<string>>? headers, ReplaceNodeOptions options);
(IBodyData? BodyData, IDictionary<string, WireMockList<string>>? Headers) Transform(IMapping mapping, IRequestMessage originalRequestMessage, IResponseMessage originalResponseMessage, IBodyData? bodyData, IDictionary<string, WireMockList<string>>? headers, ReplaceNodeOptions options);
}

View File

@@ -19,6 +19,7 @@ internal class Transformer : ITransformer
}
public (IBodyData? BodyData, IDictionary<string, WireMockList<string>>? Headers) Transform(
IMapping mapping,
IRequestMessage originalRequestMessage,
IResponseMessage originalResponseMessage,
IBodyData? bodyData,
@@ -29,6 +30,7 @@ internal class Transformer : ITransformer
var model = new
{
mapping,
request = originalRequestMessage,
response = originalResponseMessage
};
@@ -42,7 +44,7 @@ internal class Transformer : ITransformer
return (newBodyData, TransformHeaders(transformerContext, model, headers));
}
public ResponseMessage Transform(IRequestMessage requestMessage, IResponseMessage original, bool useTransformerForBodyAsFile, ReplaceNodeOptions options)
public ResponseMessage Transform(IMapping mapping, IRequestMessage requestMessage, IResponseMessage original, bool useTransformerForBodyAsFile, ReplaceNodeOptions options)
{
var transformerContext = _factory.Create();
@@ -50,6 +52,7 @@ internal class Transformer : ITransformer
var model = new
{
mapping,
request = requestMessage
};
@@ -82,22 +85,15 @@ internal class Transformer : ITransformer
return responseMessage;
}
private static IBodyData TransformBodyData(ITransformerContext transformerContext, ReplaceNodeOptions options, object model, IBodyData original, bool useTransformerForBodyAsFile)
private static IBodyData? TransformBodyData(ITransformerContext transformerContext, ReplaceNodeOptions options, object model, IBodyData original, bool useTransformerForBodyAsFile)
{
switch (original?.DetectedBodyType)
return original.DetectedBodyType switch
{
case BodyType.Json:
return TransformBodyAsJson(transformerContext, options, model, original);
case BodyType.File:
return TransformBodyAsFile(transformerContext, model, original, useTransformerForBodyAsFile);
case BodyType.String:
return TransformBodyAsString(transformerContext, model, original);
default:
return null;
}
BodyType.Json => TransformBodyAsJson(transformerContext, options, model, original),
BodyType.File => TransformBodyAsFile(transformerContext, model, original, useTransformerForBodyAsFile),
BodyType.String => TransformBodyAsString(transformerContext, model, original),
_ => null
};
}
private static IDictionary<string, WireMockList<string>> TransformHeaders(ITransformerContext transformerContext, object model, IDictionary<string, WireMockList<string>>? original)
@@ -166,11 +162,17 @@ internal class Transformer : ITransformer
{
const string property = "_";
JObject dummy = JObject.Parse($"{{ \"{property}\": null }}");
JToken node = dummy[property];
if (dummy[property] == null)
{
// TODO: check if just returning null is fine
return string.Empty;
}
JToken node = dummy[property]!;
ReplaceNodeValue(options, node, transformedString);
return dummy[property];
return dummy[property]!;
}
return stringValue;

View File

@@ -0,0 +1,16 @@
using System;
namespace WireMock.Util;
internal interface IGuidUtils
{
Guid NewGuid();
}
internal class GuidUtils : IGuidUtils
{
public Guid NewGuid()
{
return Guid.NewGuid();
}
}

View File

@@ -98,7 +98,7 @@
<ItemGroup Condition=" '$(TargetFramework)' == 'net46' ">
<PackageReference Include="Microsoft.AspNet.WebApi.OwinSelfHost" Version="5.2.6" />
<PackageReference Include="Microsoft.Owin" Version="4.1.1" />
<PackageReference Include="Microsoft.Owin" Version="4.2.2" />
<PackageReference Include="Microsoft.Owin.Host.HttpListener" Version="4.0.0" />
<PackageReference Include="Microsoft.Owin.Hosting" Version="4.0.0" />
<PackageReference Include="System.Net.Http" Version="4.3.4" />

View File

@@ -1,5 +1,6 @@
using System;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
@@ -320,6 +321,156 @@ public class WireMockAssertionsTests : IDisposable
$"Expected _server to have been called from client IP \"different-ip\", but didn't find it among the calls from IP(s) {{\"{clientIP}\"}}.");
}
[Fact]
public async Task HaveReceivedNoCalls_UsingPost_WhenACallWasNotMadeUsingPost_Should_BeOK()
{
await _httpClient.GetAsync("anyurl").ConfigureAwait(false);
_server.Should()
.HaveReceivedNoCalls()
.UsingPost();
}
[Fact]
public async Task HaveReceived2Calls_UsingDelete_WhenACallWasMadeUsingDelete_Should_BeOK()
{
await _httpClient.DeleteAsync("anyurl").ConfigureAwait(false);
await _httpClient.DeleteAsync("anyurl").ConfigureAwait(false);
await _httpClient.GetAsync("anyurl").ConfigureAwait(false);
_server.Should()
.HaveReceived(2).Calls()
.UsingDelete();
}
[Fact]
public void HaveReceivedACall_UsingPatch_Should_ThrowWhenNoCallsWereMade()
{
Action act = () => _server.Should()
.HaveReceivedACall()
.UsingPatch();
act.Should().Throw<Exception>()
.And.Message.Should()
.Be(
"Expected _server to have been called using method \"PATCH\", but no calls were made.");
}
[Fact]
public async Task HaveReceivedACall_UsingOptions_Should_ThrowWhenCallsWereNotMadeUsingOptions()
{
await _httpClient.PostAsync("anyurl", new StringContent("anycontent")).ConfigureAwait(false);
Action act = () => _server.Should()
.HaveReceivedACall()
.UsingOptions();
act.Should().Throw<Exception>()
.And.Message.Should()
.Be(
"Expected _server to have been called using method \"OPTIONS\", but didn't find it among the methods {\"POST\"}.");
}
#if !NET452
[Fact]
public async Task HaveReceivedACall_UsingConnect_WhenACallWasMadeUsingConnect_Should_BeOK()
{
_server.ResetMappings();
_server.Given(Request.Create().UsingAnyMethod())
.RespondWith(Response.Create().WithStatusCode(HttpStatusCode.Found));
_httpClient.DefaultRequestHeaders.Add("Host", new Uri(_server.Urls[0]).Authority);
await _httpClient.SendAsync(new HttpRequestMessage(new HttpMethod("CONNECT"), "anyurl")).ConfigureAwait(false);
_server.Should()
.HaveReceivedACall()
.UsingConnect();
}
#endif
[Fact]
public async Task HaveReceivedACall_UsingDelete_WhenACallWasMadeUsingDelete_Should_BeOK()
{
await _httpClient.SendAsync(new HttpRequestMessage(new HttpMethod("DELETE"), "anyurl")).ConfigureAwait(false);
_server.Should()
.HaveReceivedACall()
.UsingDelete();
}
[Fact]
public async Task HaveReceivedACall_UsingGet_WhenACallWasMadeUsingGet_Should_BeOK()
{
await _httpClient.SendAsync(new HttpRequestMessage(new HttpMethod("GET"), "anyurl")).ConfigureAwait(false);
_server.Should()
.HaveReceivedACall()
.UsingGet();
}
[Fact]
public async Task HaveReceivedACall_UsingHead_WhenACallWasMadeUsingHead_Should_BeOK()
{
await _httpClient.SendAsync(new HttpRequestMessage(new HttpMethod("HEAD"), "anyurl")).ConfigureAwait(false);
_server.Should()
.HaveReceivedACall()
.UsingHead();
}
[Fact]
public async Task HaveReceivedACall_UsingOptions_WhenACallWasMadeUsingOptions_Should_BeOK()
{
await _httpClient.SendAsync(new HttpRequestMessage(new HttpMethod("OPTIONS"), "anyurl")).ConfigureAwait(false);
_server.Should()
.HaveReceivedACall()
.UsingOptions();
}
[Fact]
public async Task HaveReceivedACall_UsingPost_WhenACallWasMadeUsingPost_Should_BeOK()
{
await _httpClient.SendAsync(new HttpRequestMessage(new HttpMethod("POST"), "anyurl")).ConfigureAwait(false);
_server.Should()
.HaveReceivedACall()
.UsingPost();
}
[Fact]
public async Task HaveReceivedACall_UsingPatch_WhenACallWasMadeUsingPatch_Should_BeOK()
{
await _httpClient.SendAsync(new HttpRequestMessage(new HttpMethod("PATCH"), "anyurl")).ConfigureAwait(false);
_server.Should()
.HaveReceivedACall()
.UsingPatch();
}
[Fact]
public async Task HaveReceivedACall_UsingPut_WhenACallWasMadeUsingPut_Should_BeOK()
{
await _httpClient.SendAsync(new HttpRequestMessage(new HttpMethod("PUT"), "anyurl")).ConfigureAwait(false);
_server.Should()
.HaveReceivedACall()
.UsingPut();
}
[Fact]
public async Task HaveReceivedACall_UsingTrace_WhenACallWasMadeUsingTrace_Should_BeOK()
{
await _httpClient.SendAsync(new HttpRequestMessage(new HttpMethod("TRACE"), "anyurl")).ConfigureAwait(false);
_server.Should()
.HaveReceivedACall()
.UsingTrace();
}
public void Dispose()
{
_server?.Stop();

View File

@@ -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<RequestMessage>())).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<RequestMessage>())).ReturnsAsync((new ResponseMessage(), newMappingFromProxy));
var requestBuilder = Request.Create().UsingAnyMethod();

View File

@@ -1,30 +1,31 @@
using System.Threading.Tasks;
using Moq;
using NFluent;
using WireMock.Models;
using WireMock.ResponseBuilders;
using WireMock.Settings;
using Xunit;
namespace WireMock.Net.Tests.ResponseBuilders
namespace WireMock.Net.Tests.ResponseBuilders;
public class ResponseCreateTests
{
public class ResponseCreateTests
private readonly WireMockServerSettings _settings = new ();
[Fact]
public async Task Response_Create_Func()
{
private readonly WireMockServerSettings _settings = new WireMockServerSettings();
// Assign
var responseMessage = new ResponseMessage { StatusCode = 500 };
var request = new RequestMessage(new UrlDetails("http://localhost"), "GET", "::1");
var mapping = new Mock<IMapping>().Object;
[Fact]
public async Task Response_Create_Func()
{
// Assign
var responseMessage = new ResponseMessage { StatusCode = 500 };
var request = new RequestMessage(new UrlDetails("http://localhost"), "GET", "::1");
var responseBuilder = Response.Create(() => responseMessage);
var responseBuilder = Response.Create(() => responseMessage);
// Act
var response = await responseBuilder.ProvideResponseAsync(mapping, request, _settings).ConfigureAwait(false);
// Act
var response = await responseBuilder.ProvideResponseAsync(request, _settings).ConfigureAwait(false);
// Assert
Check.That(response.Message).Equals(responseMessage);
}
// Assert
Check.That(response.Message).Equals(responseMessage);
}
}

View File

@@ -19,11 +19,14 @@ public class ResponseWithBodyTests
{
private const string ClientIp = "::1";
private readonly Mock<IMapping> _mappingMock;
private readonly Mock<IFileSystemHandler> _filesystemHandlerMock;
private readonly WireMockServerSettings _settings = new WireMockServerSettings();
private readonly WireMockServerSettings _settings = new ();
public ResponseWithBodyTests()
{
_mappingMock = new Mock<IMapping>();
_filesystemHandlerMock = new Mock<IFileSystemHandler>(MockBehavior.Strict);
_filesystemHandlerMock.Setup(fs => fs.ReadResponseBodyAsString(It.IsAny<string>())).Returns("abc");
@@ -44,7 +47,7 @@ public class ResponseWithBodyTests
var responseBuilder = Response.Create().WithBody(new byte[] { 48, 49 }, BodyDestinationFormat.String, Encoding.ASCII);
// act
var response = await responseBuilder.ProvideResponseAsync(request, _settings).ConfigureAwait(false);
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
// then
Check.That(response.Message.BodyData.BodyAsString).Equals("01");
@@ -66,7 +69,7 @@ public class ResponseWithBodyTests
var responseBuilder = Response.Create().WithBody(new byte[] { 48, 49 }, BodyDestinationFormat.SameAsSource, Encoding.ASCII);
// act
var response = await responseBuilder.ProvideResponseAsync(request, _settings).ConfigureAwait(false);
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
// then
Check.That(response.Message.BodyData.BodyAsBytes).ContainsExactly(new byte[] { 48, 49 });
@@ -88,7 +91,7 @@ public class ResponseWithBodyTests
var responseBuilder = Response.Create().WithBody("test", null, Encoding.ASCII);
// act
var response = await responseBuilder.ProvideResponseAsync(request, _settings).ConfigureAwait(false);
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
// then
Check.That(response.Message.BodyData.BodyAsString).Equals("test");
@@ -110,7 +113,7 @@ public class ResponseWithBodyTests
var responseBuilder = Response.Create().WithBodyAsJson(x, Encoding.ASCII);
// act
var response = await responseBuilder.ProvideResponseAsync(request, _settings).ConfigureAwait(false);
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
// then
Check.That(response.Message.BodyData.BodyAsJson).Equals(x);
@@ -132,7 +135,7 @@ public class ResponseWithBodyTests
var responseBuilder = Response.Create().WithBodyAsJson(x, true);
// act
var response = await responseBuilder.ProvideResponseAsync(request, _settings).ConfigureAwait(false);
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
// then
Check.That(response.Message.BodyData.BodyAsJson).Equals(x);
@@ -148,7 +151,7 @@ public class ResponseWithBodyTests
var responseBuilder = Response.Create().WithBody("r", BodyDestinationFormat.SameAsSource, Encoding.ASCII);
// Act
var response = await responseBuilder.ProvideResponseAsync(request, _settings).ConfigureAwait(false);
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
// Assert
Check.That(response.Message.BodyData.BodyAsBytes).IsNull();
@@ -166,7 +169,7 @@ public class ResponseWithBodyTests
var responseBuilder = Response.Create().WithBody("r", BodyDestinationFormat.Bytes, Encoding.ASCII);
// Act
var response = await responseBuilder.ProvideResponseAsync(request, _settings).ConfigureAwait(false);
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
// Assert
Check.That(response.Message.BodyData.BodyAsString).IsNull();
@@ -184,7 +187,7 @@ public class ResponseWithBodyTests
var responseBuilder = Response.Create().WithBody("{ \"value\": 42 }", BodyDestinationFormat.Json, Encoding.ASCII);
// Act
var response = await responseBuilder.ProvideResponseAsync(request, _settings).ConfigureAwait(false);
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
// Assert
Check.That(response.Message.BodyData.BodyAsString).IsNull();
@@ -206,7 +209,7 @@ public class ResponseWithBodyTests
.WithBody(req => $"path: {req.Path}");
// Act
var response = await responseBuilder.ProvideResponseAsync(request, _settings).ConfigureAwait(false);
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
// Assert
Check.That(response.Message.BodyData.BodyAsString).IsEqualTo("path: /test");
@@ -235,7 +238,7 @@ public class ResponseWithBodyTests
});
// Act
var response = await responseBuilder.ProvideResponseAsync(request, _settings).ConfigureAwait(false);
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
// Assert
Check.That(response.Message.BodyData.BodyAsString).IsEqualTo("path: /test");
@@ -263,8 +266,8 @@ public class ResponseWithBodyTests
.WithTransformer();
// Act
var response1 = await responseBuilder.ProvideResponseAsync(request1, _settings).ConfigureAwait(false);
var response2 = await responseBuilder.ProvideResponseAsync(request2, _settings).ConfigureAwait(false);
var response1 = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request1, _settings).ConfigureAwait(false);
var response2 = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request2, _settings).ConfigureAwait(false);
// Assert
Check.That(((JToken)response1.Message.BodyData.BodyAsJson).SelectToken("id")?.Value<int>()).IsEqualTo(request1Id);
@@ -288,7 +291,7 @@ public class ResponseWithBodyTests
var responseBuilder = Response.Create().WithStatusCode(200).WithBody(fileContents);
var response = await responseBuilder.ProvideResponseAsync(request1, _settings).ConfigureAwait(false);
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request1, _settings).ConfigureAwait(false);
Check.That(response.Message.StatusCode).IsEqualTo(200);
Check.That(response.Message.BodyData.BodyAsString).Contains(fileContents);
@@ -304,7 +307,7 @@ public class ResponseWithBodyTests
var responseBuilder = Response.Create().WithStatusCode(200).WithBody(fileContents);
var response = await responseBuilder.ProvideResponseAsync(request1, _settings).ConfigureAwait(false);
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request1, _settings).ConfigureAwait(false);
Check.That(response.Message.StatusCode).IsEqualTo(200);
Check.That(response.Message.BodyData.BodyAsString).Contains(fileContents);
@@ -320,7 +323,7 @@ public class ResponseWithBodyTests
var responseBuilder = Response.Create().WithStatusCode(200).WithBody("File deleted.");
var response = await responseBuilder.ProvideResponseAsync(request1, _settings).ConfigureAwait(false);
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request1, _settings).ConfigureAwait(false);
Check.That(response.Message.StatusCode).IsEqualTo(200);
Check.That(response.Message.BodyData.BodyAsString).Contains("File deleted.");
@@ -341,7 +344,7 @@ public class ResponseWithBodyTests
var responseBuilder = Response.Create().WithBody(new { foo = "bar", n = 42 }, new JsonConverter.System.Text.Json.SystemTextJsonConverter());
// Act
var response = await responseBuilder.ProvideResponseAsync(request, _settings).ConfigureAwait(false);
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
// Assert
response.Message.BodyData!.BodyAsString.Should().Be(@"{""foo"":""bar"",""n"":42}");

View File

@@ -11,59 +11,37 @@ using WireMock.Types;
using WireMock.Util;
using Xunit;
namespace WireMock.Net.Tests.ResponseBuilders
namespace WireMock.Net.Tests.ResponseBuilders;
public class ResponseWithCallbackTests
{
public class ResponseWithCallbackTests
private const string ClientIp = "::1";
private readonly Mock<IMapping> _mappingMock;
private readonly Mock<IFileSystemHandler> _filesystemHandlerMock;
private readonly WireMockServerSettings _settings = new();
public ResponseWithCallbackTests()
{
private const string ClientIp = "::1";
_mappingMock = new Mock<IMapping>();
private readonly Mock<IFileSystemHandler> _filesystemHandlerMock;
private readonly WireMockServerSettings _settings = new WireMockServerSettings();
_filesystemHandlerMock = new Mock<IFileSystemHandler>(MockBehavior.Strict);
_filesystemHandlerMock.Setup(fs => fs.ReadResponseBodyAsString(It.IsAny<string>())).Returns("abc");
public ResponseWithCallbackTests()
{
_filesystemHandlerMock = new Mock<IFileSystemHandler>(MockBehavior.Strict);
_filesystemHandlerMock.Setup(fs => fs.ReadResponseBodyAsString(It.IsAny<string>())).Returns("abc");
_settings.FileSystemHandler = _filesystemHandlerMock.Object;
}
_settings.FileSystemHandler = _filesystemHandlerMock.Object;
}
[Fact]
public async Task Response_WithCallbackAsync()
{
// Assign
var requestMessage = new RequestMessage(new UrlDetails("http://localhost/foo"), "GET", "::1");
var responseBuilder = Response.Create()
.WithCallback(async request =>
{
await Task.Delay(1);
[Fact]
public async Task Response_WithCallbackAsync()
{
// Assign
var requestMessage = new RequestMessage(new UrlDetails("http://localhost/foo"), "GET", "::1");
var responseBuilder = 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 response = await responseBuilder.ProvideResponseAsync(requestMessage, _settings).ConfigureAwait(false);
// Assert
response.Message.BodyData.BodyAsString.Should().Be("/fooBar");
response.Message.StatusCode.Should().Be(302);
}
[Fact]
public async Task Response_WithCallback()
{
// Assign
var requestMessage = new RequestMessage(new UrlDetails("http://localhost/foo"), "GET", "::1");
var responseBuilder = Response.Create()
.WithCallback(request => new ResponseMessage
return new ResponseMessage
{
BodyData = new BodyData
{
@@ -71,101 +49,125 @@ namespace WireMock.Net.Tests.ResponseBuilders
BodyAsString = request.Path + "Bar"
},
StatusCode = 302
});
};
});
// Act
var response = await responseBuilder.ProvideResponseAsync(requestMessage, _settings).ConfigureAwait(false);
// Act
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, requestMessage, _settings).ConfigureAwait(false);
// Assert
response.Message.BodyData.BodyAsString.Should().Be("/fooBar");
response.Message.StatusCode.Should().Be(302);
}
// Assert
response.Message.BodyData.BodyAsString.Should().Be("/fooBar");
response.Message.StatusCode.Should().Be(302);
}
[Fact]
public async Task Response_WithCallback_ShouldUseStatusCodeAndHeaderInTheCallback()
{
// Assign
var header = "X-UserId";
var requestMessage = new RequestMessage(new UrlDetails("http://localhost/foo"), "GET", "::1");
var responseBuilder = Response.Create()
.WithCallback(request => new ResponseMessage
[Fact]
public async Task Response_WithCallback()
{
// Assign
var requestMessage = new RequestMessage(new UrlDetails("http://localhost/foo"), "GET", "::1");
var responseBuilder = Response.Create()
.WithCallback(request => new ResponseMessage
{
BodyData = new BodyData
{
BodyData = new BodyData
{
DetectedBodyType = BodyType.String,
BodyAsString = request.Path + "Bar"
},
StatusCode = HttpStatusCode.Accepted,
Headers = new Dictionary<string, WireMockList<string>>
{
{ header, new WireMockList<string>("Stef") }
}
});
DetectedBodyType = BodyType.String,
BodyAsString = request.Path + "Bar"
},
StatusCode = 302
});
// Act
var response = await responseBuilder.ProvideResponseAsync(requestMessage, _settings).ConfigureAwait(false);
// Act
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, requestMessage, _settings).ConfigureAwait(false);
// Assert
response.Message.BodyData.BodyAsString.Should().Be("/fooBar");
response.Message.StatusCode.Should().Be(HttpStatusCode.Accepted);
response.Message.Headers[header].Should().ContainSingle("Stef");
}
// Assert
response.Message.BodyData.BodyAsString.Should().Be("/fooBar");
response.Message.StatusCode.Should().Be(302);
}
[Fact]
public async Task Response_WithCallback_And_Additional_WithStatusCode_And_WithHeader_ShouldUseAdditional()
{
// Assign
var header = "X-UserId";
var requestMessage = new RequestMessage(new UrlDetails("http://localhost/foo"), "GET", "::1");
var responseBuilder = Response.Create()
.WithCallback(request => new ResponseMessage
[Fact]
public async Task Response_WithCallback_ShouldUseStatusCodeAndHeaderInTheCallback()
{
// Assign
var header = "X-UserId";
var requestMessage = new RequestMessage(new UrlDetails("http://localhost/foo"), "GET", "::1");
var responseBuilder = Response.Create()
.WithCallback(request => new ResponseMessage
{
BodyData = new BodyData
{
BodyData = new BodyData
{
DetectedBodyType = BodyType.String,
BodyAsString = request.Path + "Bar"
},
StatusCode = HttpStatusCode.NotFound,
Headers = new Dictionary<string, WireMockList<string>>
{
{ header, new WireMockList<string>("NA") }
}
})
.WithStatusCode(HttpStatusCode.Accepted)
.WithHeader(header, "Stef");
// Act
var response = await responseBuilder.ProvideResponseAsync(requestMessage, _settings).ConfigureAwait(false);
// Assert
response.Message.BodyData.BodyAsString.Should().Be("/fooBar");
response.Message.StatusCode.Should().Be((int) HttpStatusCode.Accepted);
response.Message.Headers[header].Should().ContainSingle("Stef");
}
[Fact]
public async Task Response_WithCallback_And_UseTransformer_Is_True()
{
// Assign
var requestMessage = new RequestMessage(new UrlDetails("http://localhost/foo"), "GET", "::1");
var responseBuilder = Response.Create()
.WithCallback(request => new ResponseMessage
DetectedBodyType = BodyType.String,
BodyAsString = request.Path + "Bar"
},
StatusCode = HttpStatusCode.Accepted,
Headers = new Dictionary<string, WireMockList<string>>
{
BodyData = new BodyData
{
DetectedBodyType = BodyType.String,
BodyAsString = "{{request.Path}}Bar"
},
StatusCode = 302
})
.WithTransformer();
{ header, new WireMockList<string>("Stef") }
}
});
// Act
var response = await responseBuilder.ProvideResponseAsync(requestMessage, _settings).ConfigureAwait(false);
// Act
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, requestMessage, _settings).ConfigureAwait(false);
// Assert
response.Message.BodyData.BodyAsString.Should().Be("/fooBar");
response.Message.StatusCode.Should().Be(302);
}
// Assert
response.Message.BodyData.BodyAsString.Should().Be("/fooBar");
response.Message.StatusCode.Should().Be(HttpStatusCode.Accepted);
response.Message.Headers[header].Should().ContainSingle("Stef");
}
[Fact]
public async Task Response_WithCallback_And_Additional_WithStatusCode_And_WithHeader_ShouldUseAdditional()
{
// Assign
var header = "X-UserId";
var requestMessage = new RequestMessage(new UrlDetails("http://localhost/foo"), "GET", "::1");
var responseBuilder = Response.Create()
.WithCallback(request => new ResponseMessage
{
BodyData = new BodyData
{
DetectedBodyType = BodyType.String,
BodyAsString = request.Path + "Bar"
},
StatusCode = HttpStatusCode.NotFound,
Headers = new Dictionary<string, WireMockList<string>>
{
{ header, new WireMockList<string>("NA") }
}
})
.WithStatusCode(HttpStatusCode.Accepted)
.WithHeader(header, "Stef");
// Act
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, requestMessage, _settings).ConfigureAwait(false);
// Assert
response.Message.BodyData.BodyAsString.Should().Be("/fooBar");
response.Message.StatusCode.Should().Be((int)HttpStatusCode.Accepted);
response.Message.Headers[header].Should().ContainSingle("Stef");
}
[Fact]
public async Task Response_WithCallback_And_UseTransformer_Is_True()
{
// Assign
var requestMessage = new RequestMessage(new UrlDetails("http://localhost/foo"), "GET", "::1");
var responseBuilder = Response.Create()
.WithCallback(request => new ResponseMessage
{
BodyData = new BodyData
{
DetectedBodyType = BodyType.String,
BodyAsString = "{{request.Path}}Bar"
},
StatusCode = 302
})
.WithTransformer();
// Act
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, requestMessage, _settings).ConfigureAwait(false);
// Assert
response.Message.BodyData.BodyAsString.Should().Be("/fooBar");
response.Message.StatusCode.Should().Be(302);
}
}

View File

@@ -1,48 +1,55 @@
using System.Threading.Tasks;
using FluentAssertions;
using Moq;
using WireMock.Models;
using WireMock.ResponseBuilders;
using WireMock.Settings;
using Xunit;
namespace WireMock.Net.Tests.ResponseBuilders
namespace WireMock.Net.Tests.ResponseBuilders;
public class ResponseWithFaultTests
{
public class ResponseWithFaultTests
private readonly WireMockServerSettings _settings = new();
private const string ClientIp = "::1";
private readonly Mock<IMapping> _mappingMock;
public ResponseWithFaultTests()
{
private readonly WireMockServerSettings _settings = new WireMockServerSettings();
private const string ClientIp = "::1";
[Theory]
[InlineData(FaultType.EMPTY_RESPONSE)]
[InlineData(FaultType.MALFORMED_RESPONSE_CHUNK)]
public async Task Response_ProvideResponse_WithFault(FaultType faultType)
{
// Arrange
var request = new RequestMessage(new UrlDetails("http://localhost/fault"), "GET", ClientIp);
// Act
var responseBuilder = Response.Create().WithFault(faultType);
var response = await responseBuilder.ProvideResponseAsync(request, _settings).ConfigureAwait(false);
// Assert
response.Message.FaultType.Should().Be(faultType);
response.Message.FaultPercentage.Should().BeNull();
}
[Theory]
[InlineData(FaultType.EMPTY_RESPONSE, 0.5)]
public async Task Response_ProvideResponse_WithFault_IncludingPercentage(FaultType faultType, double percentage)
{
// Arrange
var request = new RequestMessage(new UrlDetails("http://localhost/fault"), "GET", ClientIp);
// Act
var responseBuilder = Response.Create().WithFault(faultType, percentage);
var response = await responseBuilder.ProvideResponseAsync(request, _settings).ConfigureAwait(false);
// Assert
response.Message.FaultType.Should().Be(faultType);
response.Message.FaultPercentage.Should().Be(percentage);
}
_mappingMock = new Mock<IMapping>();
}
}
[Theory]
[InlineData(FaultType.EMPTY_RESPONSE)]
[InlineData(FaultType.MALFORMED_RESPONSE_CHUNK)]
public async Task Response_ProvideResponse_WithFault(FaultType faultType)
{
// Arrange
var request = new RequestMessage(new UrlDetails("http://localhost/fault"), "GET", ClientIp);
// Act
var responseBuilder = Response.Create().WithFault(faultType);
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
// Assert
response.Message.FaultType.Should().Be(faultType);
response.Message.FaultPercentage.Should().BeNull();
}
[Theory]
[InlineData(FaultType.EMPTY_RESPONSE, 0.5)]
public async Task Response_ProvideResponse_WithFault_IncludingPercentage(FaultType faultType, double percentage)
{
// Arrange
var request = new RequestMessage(new UrlDetails("http://localhost/fault"), "GET", ClientIp);
// Act
var responseBuilder = Response.Create().WithFault(faultType, percentage);
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
// Assert
response.Message.FaultType.Should().Be(faultType);
response.Message.FaultPercentage.Should().Be(percentage);
}
}

View File

@@ -9,91 +9,94 @@ using WireMock.ResponseBuilders;
using WireMock.Settings;
using Xunit;
namespace WireMock.Net.Tests.ResponseBuilders
namespace WireMock.Net.Tests.ResponseBuilders;
public class ResponseWithHandlebarsFileTests
{
public class ResponseWithHandlebarsFileTests
private readonly WireMockServerSettings _settings = new();
private const string ClientIp = "::1";
private readonly Mock<IMapping> _mappingMock;
private readonly Mock<IFileSystemHandler> _filesystemHandlerMock;
public ResponseWithHandlebarsFileTests()
{
private readonly Mock<IFileSystemHandler> _filesystemHandlerMock;
private readonly WireMockServerSettings _settings = new WireMockServerSettings();
private const string ClientIp = "::1";
_mappingMock = new Mock<IMapping>();
public ResponseWithHandlebarsFileTests()
{
_filesystemHandlerMock = new Mock<IFileSystemHandler>(MockBehavior.Strict);
_filesystemHandlerMock.Setup(fs => fs.ReadResponseBodyAsString(It.IsAny<string>())).Returns("abc");
_filesystemHandlerMock = new Mock<IFileSystemHandler>(MockBehavior.Strict);
_filesystemHandlerMock.Setup(fs => fs.ReadResponseBodyAsString(It.IsAny<string>())).Returns("abc");
_settings.FileSystemHandler = _filesystemHandlerMock.Object;
}
_settings.FileSystemHandler = _filesystemHandlerMock.Object;
}
[Fact]
public async Task Response_ProvideResponseAsync_Handlebars_File()
{
// Assign
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "GET", ClientIp);
[Fact]
public async Task Response_ProvideResponseAsync_Handlebars_File()
{
// Assign
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "GET", ClientIp);
var responseBuilder = Response.Create()
.WithBodyAsJson(new
{
Data = "{{File \"x.json\"}}"
})
.WithTransformer();
var responseBuilder = Response.Create()
.WithBodyAsJson(new
{
Data = "{{File \"x.json\"}}"
})
.WithTransformer();
// Act
var response = await responseBuilder.ProvideResponseAsync(request, _settings).ConfigureAwait(false);
// Act
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
// Assert
JObject j = JObject.FromObject(response.Message.BodyData.BodyAsJson);
Check.That(j["Data"].Value<string>()).Equals("abc");
// Assert
JObject j = JObject.FromObject(response.Message.BodyData.BodyAsJson);
Check.That(j["Data"].Value<string>()).Equals("abc");
// Verify
_filesystemHandlerMock.Verify(fs => fs.ReadResponseBodyAsString("x.json"), Times.Once);
_filesystemHandlerMock.VerifyNoOtherCalls();
}
// Verify
_filesystemHandlerMock.Verify(fs => fs.ReadResponseBodyAsString("x.json"), Times.Once);
_filesystemHandlerMock.VerifyNoOtherCalls();
}
[Fact]
public async Task Response_ProvideResponseAsync_Handlebars_File_Replace()
{
// Assign
var request = new RequestMessage(new UrlDetails("http://localhost:1234?id=x"), "GET", ClientIp);
[Fact]
public async Task Response_ProvideResponseAsync_Handlebars_File_Replace()
{
// Assign
var request = new RequestMessage(new UrlDetails("http://localhost:1234?id=x"), "GET", ClientIp);
var responseBuilder = Response.Create()
.WithBodyAsJson(new
{
Data = "{{File \"{{request.query.id}}.json\"}}"
})
.WithTransformer();
var responseBuilder = Response.Create()
.WithBodyAsJson(new
{
Data = "{{File \"{{request.query.id}}.json\"}}"
})
.WithTransformer();
// Act
var response = await responseBuilder.ProvideResponseAsync(request, _settings).ConfigureAwait(false);
// Act
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
// Assert
JObject j = JObject.FromObject(response.Message.BodyData.BodyAsJson);
Check.That(j["Data"].Value<string>()).Equals("abc");
// Assert
JObject j = JObject.FromObject(response.Message.BodyData.BodyAsJson);
Check.That(j["Data"].Value<string>()).Equals("abc");
// Verify
_filesystemHandlerMock.Verify(fs => fs.ReadResponseBodyAsString("x.json"), Times.Once);
_filesystemHandlerMock.VerifyNoOtherCalls();
}
// Verify
_filesystemHandlerMock.Verify(fs => fs.ReadResponseBodyAsString("x.json"), Times.Once);
_filesystemHandlerMock.VerifyNoOtherCalls();
}
[Fact]
public void Response_ProvideResponseAsync_Handlebars_File_WithMissingArgument_Throws_HandlebarsException()
{
// Assign
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "GET", ClientIp);
[Fact]
public void Response_ProvideResponseAsync_Handlebars_File_WithMissingArgument_Throws_HandlebarsException()
{
// Assign
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "GET", ClientIp);
var responseBuilder = Response.Create()
.WithBodyAsJson(new
{
Data = "{{File}}"
})
.WithTransformer();
var responseBuilder = Response.Create()
.WithBodyAsJson(new
{
Data = "{{File}}"
})
.WithTransformer();
// Act
Check.ThatAsyncCode(() => responseBuilder.ProvideResponseAsync(request, _settings)).Throws<HandlebarsException>();
// Act
Check.ThatAsyncCode(() => responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings)).Throws<HandlebarsException>();
// Verify
_filesystemHandlerMock.Verify(fs => fs.ReadResponseBodyAsString(It.IsAny<string>()), Times.Never);
_filesystemHandlerMock.VerifyNoOtherCalls();
}
// Verify
_filesystemHandlerMock.Verify(fs => fs.ReadResponseBodyAsString(It.IsAny<string>()), Times.Never);
_filesystemHandlerMock.VerifyNoOtherCalls();
}
}

View File

@@ -9,40 +9,38 @@ using WireMock.Types;
using WireMock.Util;
using Xunit;
namespace WireMock.Net.Tests.ResponseBuilders
namespace WireMock.Net.Tests.ResponseBuilders;
public class ResponseWithHandlebarsHelpersTests
{
public class ResponseWithHandlebarsHelpersTests
private const string ClientIp = "::1";
private readonly WireMockServerSettings _settings = new();
public ResponseWithHandlebarsHelpersTests()
{
private const string ClientIp = "::1";
var filesystemHandlerMock = new Mock<IFileSystemHandler>(MockBehavior.Strict);
filesystemHandlerMock.Setup(fs => fs.ReadResponseBodyAsString(It.IsAny<string>())).Returns("abc");
private readonly Mock<IFileSystemHandler> _filesystemHandlerMock;
private readonly WireMockServerSettings _settings = new WireMockServerSettings();
_settings.FileSystemHandler = filesystemHandlerMock.Object;
}
public ResponseWithHandlebarsHelpersTests()
{
_filesystemHandlerMock = new Mock<IFileSystemHandler>(MockBehavior.Strict);
_filesystemHandlerMock.Setup(fs => fs.ReadResponseBodyAsString(It.IsAny<string>())).Returns("abc");
[Fact]
public async Task Response_ProvideResponseAsync_HandlebarsHelpers_String_Uppercase()
{
// Assign
var body = new BodyData { BodyAsString = "abc", DetectedBodyType = BodyType.String };
_settings.FileSystemHandler = _filesystemHandlerMock.Object;
}
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
[Fact]
public async Task Response_ProvideResponseAsync_HandlebarsHelpers_String_Uppercase()
{
// Assign
var body = new BodyData { BodyAsString = "abc", DetectedBodyType = BodyType.String };
var responseBuilder = Response.Create()
.WithBody("{{String.Uppercase request.body}}")
.WithTransformer();
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
// Act
var response = await responseBuilder.ProvideResponseAsync(new Mock<IMapping>().Object, request, _settings).ConfigureAwait(false);
var responseBuilder = Response.Create()
.WithBody("{{String.Uppercase request.body}}")
.WithTransformer();
// Act
var response = await responseBuilder.ProvideResponseAsync(request, _settings).ConfigureAwait(false);
// assert
Check.That(response.Message.BodyData.BodyAsString).Equals("ABC");
}
// assert
Check.That(response.Message.BodyData.BodyAsString).Equals("ABC");
}
}

View File

@@ -9,42 +9,43 @@ using WireMock.ResponseBuilders;
using WireMock.Settings;
using Xunit;
namespace WireMock.Net.Tests.ResponseBuilders
namespace WireMock.Net.Tests.ResponseBuilders;
public class ResponseWithHandlebarsHumanizerTests
{
public class ResponseWithHandlebarsHumanizerTests
private const string ClientIp = "::1";
private readonly WireMockServerSettings _settings = new();
private readonly Mock<IMapping> _mappingMock;
public ResponseWithHandlebarsHumanizerTests()
{
private const string ClientIp = "::1";
_mappingMock = new Mock<IMapping>();
private readonly Mock<IFileSystemHandler> _filesystemHandlerMock;
private readonly WireMockServerSettings _settings = new WireMockServerSettings();
var filesystemHandlerMock = new Mock<IFileSystemHandler>(MockBehavior.Strict);
filesystemHandlerMock.Setup(fs => fs.ReadResponseBodyAsString(It.IsAny<string>())).Returns("abc");
public ResponseWithHandlebarsHumanizerTests()
{
_filesystemHandlerMock = new Mock<IFileSystemHandler>(MockBehavior.Strict);
_filesystemHandlerMock.Setup(fs => fs.ReadResponseBodyAsString(It.IsAny<string>())).Returns("abc");
_settings.FileSystemHandler = filesystemHandlerMock.Object;
}
_settings.FileSystemHandler = _filesystemHandlerMock.Object;
}
[Fact]
public async Task Response_ProvideResponseAsync_Handlebars_Humanizer()
{
// Assign
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "GET", ClientIp);
[Fact]
public async Task Response_ProvideResponseAsync_Handlebars_Humanizer()
{
// Assign
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "GET", ClientIp);
var responseBuilder = Response.Create()
.WithBodyAsJson(new
{
Text = string.Format("{{{{[Humanizer.Humanize] \"{0}\" }}}}", "PascalCaseInputStringIsTurnedIntoSentence")
})
.WithTransformer();
var responseBuilder = Response.Create()
.WithBodyAsJson(new
{
Text = string.Format("{{{{[Humanizer.Humanize] \"{0}\" }}}}", "PascalCaseInputStringIsTurnedIntoSentence")
})
.WithTransformer();
// Act
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
// Act
var response = await responseBuilder.ProvideResponseAsync(request, _settings).ConfigureAwait(false);
// Assert
JObject j = JObject.FromObject(response.Message.BodyData.BodyAsJson);
Check.That(j["Text"].Value<string>()).IsEqualTo("Pascal case input string is turned into sentence");
}
// Assert
JObject j = JObject.FromObject(response.Message.BodyData.BodyAsJson);
Check.That(j["Text"].Value<string>()).IsEqualTo("Pascal case input string is turned into sentence");
}
}

View File

@@ -13,30 +13,32 @@ using WireMock.Types;
using WireMock.Util;
using Xunit;
namespace WireMock.Net.Tests.ResponseBuilders
namespace WireMock.Net.Tests.ResponseBuilders;
public class ResponseWithHandlebarsJsonPathTests
{
public class ResponseWithHandlebarsJsonPathTests
private const string ClientIp = "::1";
private readonly WireMockServerSettings _settings = new();
private readonly Mock<IMapping> _mappingMock;
public ResponseWithHandlebarsJsonPathTests()
{
private const string ClientIp = "::1";
_mappingMock = new Mock<IMapping>();
private readonly Mock<IFileSystemHandler> _filesystemHandlerMock;
private readonly WireMockServerSettings _settings = new WireMockServerSettings();
var filesystemHandlerMock = new Mock<IFileSystemHandler>(MockBehavior.Strict);
filesystemHandlerMock.Setup(fs => fs.ReadResponseBodyAsString(It.IsAny<string>())).Returns("abc");
public ResponseWithHandlebarsJsonPathTests()
_settings.FileSystemHandler = filesystemHandlerMock.Object;
}
[Fact]
public async Task Response_ProvideResponse_Handlebars_JsonPath_SelectToken_Object_ResponseBodyAsJson()
{
// Assign
var body = new BodyData
{
_filesystemHandlerMock = new Mock<IFileSystemHandler>(MockBehavior.Strict);
_filesystemHandlerMock.Setup(fs => fs.ReadResponseBodyAsString(It.IsAny<string>())).Returns("abc");
_settings.FileSystemHandler = _filesystemHandlerMock.Object;
}
[Fact]
public async Task Response_ProvideResponse_Handlebars_JsonPath_SelectToken_Object_ResponseBodyAsJson()
{
// Assign
var body = new BodyData
{
BodyAsString = @"{
BodyAsString = @"{
""Stores"": [
""Lambton Quay"",
""Willis Street""
@@ -66,57 +68,57 @@ namespace WireMock.Net.Tests.ResponseBuilders
}
]
}",
DetectedBodyType = BodyType.String
};
DetectedBodyType = BodyType.String
};
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
var responseBuilder = Response.Create()
.WithHeader("Content-Type", "application/json")
.WithBodyAsJson(new { x = "{{JsonPath.SelectToken request.body \"$.Manufacturers[?(@.Name == 'Acme Co')]\"}}" })
.WithTransformer();
var responseBuilder = Response.Create()
.WithHeader("Content-Type", "application/json")
.WithBodyAsJson(new { x = "{{JsonPath.SelectToken request.body \"$.Manufacturers[?(@.Name == 'Acme Co')]\"}}" })
.WithTransformer();
// Act
var response = await responseBuilder.ProvideResponseAsync(request, _settings).ConfigureAwait(false);
// Act
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
// Assert
JObject j = JObject.FromObject(response.Message.BodyData.BodyAsJson);
Check.That(j["x"]).IsNotNull();
Check.That(j["x"]["Name"].ToString()).Equals("Acme Co");
}
// Assert
JObject j = JObject.FromObject(response.Message.BodyData.BodyAsJson);
Check.That(j["x"]).IsNotNull();
Check.That(j["x"]["Name"].ToString()).Equals("Acme Co");
}
[Fact]
public async Task Response_ProvideResponse_Handlebars_JsonPath_SelectToken_Number_ResponseBodyAsJson()
[Fact]
public async Task Response_ProvideResponse_Handlebars_JsonPath_SelectToken_Number_ResponseBodyAsJson()
{
// Assign
var body = new BodyData
{
// Assign
var body = new BodyData
{
BodyAsString = "{ \"Price\": 99 }",
DetectedBodyType = BodyType.String
};
BodyAsString = "{ \"Price\": 99 }",
DetectedBodyType = BodyType.String
};
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
var responseBuilder = Response.Create()
.WithHeader("Content-Type", "application/json")
.WithBodyAsJson(new { x = "{{JsonPath.SelectToken request.body \"..Price\"}}" })
.WithTransformer();
var responseBuilder = Response.Create()
.WithHeader("Content-Type", "application/json")
.WithBodyAsJson(new { x = "{{JsonPath.SelectToken request.body \"..Price\"}}" })
.WithTransformer();
// Act
var response = await responseBuilder.ProvideResponseAsync(request, _settings).ConfigureAwait(false);
// Act
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
// Assert
JObject j = JObject.FromObject(response.Message.BodyData.BodyAsJson);
Check.That(j["x"].Value<long>()).Equals(99);
}
// Assert
JObject j = JObject.FromObject(response.Message.BodyData.BodyAsJson);
Check.That(j["x"].Value<long>()).Equals(99);
}
[Fact]
public async Task Response_ProvideResponse_Handlebars_JsonPath_SelectToken_Request_BodyAsString()
[Fact]
public async Task Response_ProvideResponse_Handlebars_JsonPath_SelectToken_Request_BodyAsString()
{
// Assign
var body = new BodyData
{
// Assign
var body = new BodyData
{
BodyAsString = @"{
BodyAsString = @"{
""Stores"": [
""Lambton Quay"",
""Willis Street""
@@ -146,30 +148,30 @@ namespace WireMock.Net.Tests.ResponseBuilders
}
]
}",
DetectedBodyType = BodyType.String
};
DetectedBodyType = BodyType.String
};
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
var responseBuilder = Response.Create()
.WithHeader("Content-Type", "application/json")
.WithBody("{{JsonPath.SelectToken request.body \"$.Manufacturers[?(@.Name == 'Acme Co')]\"}}")
.WithTransformer();
var responseBuilder = Response.Create()
.WithHeader("Content-Type", "application/json")
.WithBody("{{JsonPath.SelectToken request.body \"$.Manufacturers[?(@.Name == 'Acme Co')]\"}}")
.WithTransformer();
// Act
var response = await responseBuilder.ProvideResponseAsync(request, _settings).ConfigureAwait(false);
// Act
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
// Assert
Check.That(response.Message.BodyData.BodyAsString).Equals($"{{{Environment.NewLine} \"Name\": \"Acme Co\",{Environment.NewLine} \"Products\": [{Environment.NewLine} {{{Environment.NewLine} \"Name\": \"Anvil\",{Environment.NewLine} \"Price\": 50{Environment.NewLine} }}{Environment.NewLine} ]{Environment.NewLine}}}");
}
// Assert
Check.That(response.Message.BodyData.BodyAsString).Equals($"{{{Environment.NewLine} \"Name\": \"Acme Co\",{Environment.NewLine} \"Products\": [{Environment.NewLine} {{{Environment.NewLine} \"Name\": \"Anvil\",{Environment.NewLine} \"Price\": 50{Environment.NewLine} }}{Environment.NewLine} ]{Environment.NewLine}}}");
}
[Fact]
public async Task Response_ProvideResponse_Handlebars_JsonPath_SelectToken_Request_BodyAsJObject()
[Fact]
public async Task Response_ProvideResponse_Handlebars_JsonPath_SelectToken_Request_BodyAsJObject()
{
// Assign
var body = new BodyData
{
// Assign
var body = new BodyData
{
BodyAsJson = JObject.Parse(@"{
BodyAsJson = JObject.Parse(@"{
'Stores': [
'Lambton Quay',
'Willis Street'
@@ -199,30 +201,30 @@ namespace WireMock.Net.Tests.ResponseBuilders
}
]
}"),
DetectedBodyType = BodyType.Json
};
DetectedBodyType = BodyType.Json
};
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
var responseBuilder = Response.Create()
.WithHeader("Content-Type", "application/json")
.WithBody("{{JsonPath.SelectToken request.bodyAsJson \"$.Manufacturers[?(@.Name == 'Acme Co')]\"}}")
.WithTransformer();
var responseBuilder = Response.Create()
.WithHeader("Content-Type", "application/json")
.WithBody("{{JsonPath.SelectToken request.bodyAsJson \"$.Manufacturers[?(@.Name == 'Acme Co')]\"}}")
.WithTransformer();
// Act
var response = await responseBuilder.ProvideResponseAsync(request, _settings).ConfigureAwait(false);
// Act
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
// Assert
Check.That(response.Message.BodyData.BodyAsString).Equals($"{{{Environment.NewLine} \"Name\": \"Acme Co\",{Environment.NewLine} \"Products\": [{Environment.NewLine} {{{Environment.NewLine} \"Name\": \"Anvil\",{Environment.NewLine} \"Price\": 50{Environment.NewLine} }}{Environment.NewLine} ]{Environment.NewLine}}}");
}
// Assert
Check.That(response.Message.BodyData.BodyAsString).Equals($"{{{Environment.NewLine} \"Name\": \"Acme Co\",{Environment.NewLine} \"Products\": [{Environment.NewLine} {{{Environment.NewLine} \"Name\": \"Anvil\",{Environment.NewLine} \"Price\": 50{Environment.NewLine} }}{Environment.NewLine} ]{Environment.NewLine}}}");
}
[Fact]
public async Task Response_ProvideResponse_Handlebars_JsonPath_SelectTokens_Request_BodyAsString()
[Fact]
public async Task Response_ProvideResponse_Handlebars_JsonPath_SelectTokens_Request_BodyAsString()
{
// Assign
var body = new BodyData
{
// Assign
var body = new BodyData
{
BodyAsString = @"{
BodyAsString = @"{
""Stores"": [
""Lambton Quay"",
""Willis Street""
@@ -252,30 +254,30 @@ namespace WireMock.Net.Tests.ResponseBuilders
}
]
}",
DetectedBodyType = BodyType.String
};
DetectedBodyType = BodyType.String
};
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
var responseBuilder = Response.Create()
.WithHeader("Content-Type", "application/json")
.WithBody("{{#JsonPath.SelectTokens request.body \"$..Products[?(@.Price >= 50)].Name\"}}{{#each this}}%{{@index}}:{{this}}%{{/each}}{{/JsonPath.SelectTokens}}")
.WithTransformer();
var responseBuilder = Response.Create()
.WithHeader("Content-Type", "application/json")
.WithBody("{{#JsonPath.SelectTokens request.body \"$..Products[?(@.Price >= 50)].Name\"}}{{#each this}}%{{@index}}:{{this}}%{{/each}}{{/JsonPath.SelectTokens}}")
.WithTransformer();
// Act
var response = await responseBuilder.ProvideResponseAsync(request, _settings).ConfigureAwait(false);
// Act
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
// Assert
Check.That(response.Message.BodyData.BodyAsString).Equals("%0:Anvil%%1:Elbow Grease%");
}
// Assert
Check.That(response.Message.BodyData.BodyAsString).Equals("%0:Anvil%%1:Elbow Grease%");
}
[Fact]
public async Task Response_ProvideResponse_Handlebars_JsonPath_SelectTokens_Request_BodyAsJObject()
[Fact]
public async Task Response_ProvideResponse_Handlebars_JsonPath_SelectTokens_Request_BodyAsJObject()
{
// Assign
var body = new BodyData
{
// Assign
var body = new BodyData
{
BodyAsJson = JObject.Parse(@"{
BodyAsJson = JObject.Parse(@"{
'Stores': [
'Lambton Quay',
'Willis Street'
@@ -305,74 +307,73 @@ namespace WireMock.Net.Tests.ResponseBuilders
}
]
}"),
DetectedBodyType = BodyType.Json
};
DetectedBodyType = BodyType.Json
};
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
var responseBuilder = Response.Create()
.WithHeader("Content-Type", "application/json")
.WithBody("{{#JsonPath.SelectTokens request.bodyAsJson \"$..Products[?(@.Price >= 50)].Name\"}}{{#each this}}%{{@index}}:{{this}}%{{/each}}{{/JsonPath.SelectTokens}}")
.WithTransformer();
var responseBuilder = Response.Create()
.WithHeader("Content-Type", "application/json")
.WithBody("{{#JsonPath.SelectTokens request.bodyAsJson \"$..Products[?(@.Price >= 50)].Name\"}}{{#each this}}%{{@index}}:{{this}}%{{/each}}{{/JsonPath.SelectTokens}}")
.WithTransformer();
// Act
var response = await responseBuilder.ProvideResponseAsync(request, _settings).ConfigureAwait(false);
// Act
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
// Assert
Check.That(response.Message.BodyData.BodyAsString).Equals("%0:Anvil%%1:Elbow Grease%");
}
// Assert
Check.That(response.Message.BodyData.BodyAsString).Equals("%0:Anvil%%1:Elbow Grease%");
}
[Fact]
public void Response_ProvideResponse_Handlebars_JsonPath_SelectTokens_Throws()
[Fact]
public void Response_ProvideResponse_Handlebars_JsonPath_SelectTokens_Throws()
{
// Assign
var body = new BodyData
{
// Assign
var body = new BodyData
{
BodyAsJson = JObject.Parse(@"{
BodyAsJson = JObject.Parse(@"{
'Stores': [
'Lambton Quay',
'Willis Street'
]
}"),
DetectedBodyType = BodyType.Json
};
DetectedBodyType = BodyType.Json
};
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
var responseBuilder = Response.Create()
.WithHeader("Content-Type", "application/json")
.WithBody("{{#JsonPath.SelectTokens request.body \"$..Products[?(@.Price >= 50)].Name\"}}{{id}} {{value}},{{/JsonPath.SelectTokens}}")
.WithTransformer();
var responseBuilder = Response.Create()
.WithHeader("Content-Type", "application/json")
.WithBody("{{#JsonPath.SelectTokens request.body \"$..Products[?(@.Price >= 50)].Name\"}}{{id}} {{value}},{{/JsonPath.SelectTokens}}")
.WithTransformer();
// Act
Check.ThatAsyncCode(() => responseBuilder.ProvideResponseAsync(request, _settings)).Throws<ArgumentNullException>();
}
// Act
Check.ThatAsyncCode(() => responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings)).Throws<ArgumentNullException>();
}
[Fact]
public async Task Response_ProvideResponse_Transformer_WithBodyAsFile_JsonPath()
[Fact]
public async Task Response_ProvideResponse_Transformer_WithBodyAsFile_JsonPath()
{
// Assign
string jsonString = "{ \"MyUniqueNumber\": \"1\" }";
var bodyData = new BodyData
{
// Assign
string jsonString = "{ \"MyUniqueNumber\": \"1\" }";
var bodyData = new BodyData
{
BodyAsString = jsonString,
BodyAsJson = JsonConvert.DeserializeObject(jsonString),
DetectedBodyType = BodyType.Json,
DetectedBodyTypeFromContentType = BodyType.Json,
Encoding = Encoding.UTF8
};
var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "POST", ClientIp, bodyData);
BodyAsString = jsonString,
BodyAsJson = JsonConvert.DeserializeObject(jsonString),
DetectedBodyType = BodyType.Json,
DetectedBodyTypeFromContentType = BodyType.Json,
Encoding = Encoding.UTF8
};
var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "POST", ClientIp, bodyData);
string jsonPath = "\"$.MyUniqueNumber\"";
var responseBuilder = Response.Create()
.WithTransformer()
.WithBodyFromFile(@"c:\\{{JsonPath.SelectToken request.body " + jsonPath + "}}\\test.json"); // why use a \\ here ?
string jsonPath = "\"$.MyUniqueNumber\"";
var responseBuilder = Response.Create()
.WithTransformer()
.WithBodyFromFile(@"c:\\{{JsonPath.SelectToken request.body " + jsonPath + "}}\\test.json"); // why use a \\ here ?
// Act
var response = await responseBuilder.ProvideResponseAsync(request, _settings).ConfigureAwait(false);
// Act
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
// Assert
Check.That(response.Message.BodyData.BodyAsFile).Equals(@"c:\1\test.json");
}
// Assert
Check.That(response.Message.BodyData.BodyAsFile).Equals(@"c:\1\test.json");
}
}

View File

@@ -13,237 +13,239 @@ using WireMock.Types;
using WireMock.Util;
using Xunit;
namespace WireMock.Net.Tests.ResponseBuilders
namespace WireMock.Net.Tests.ResponseBuilders;
public class ResponseWithHandlebarsLinqTests
{
public class ResponseWithHandlebarsLinqTests
private readonly WireMockServerSettings _settings = new();
private Mock<IMapping> mappingMock;
public ResponseWithHandlebarsLinqTests()
{
private readonly Mock<IFileSystemHandler> _filesystemHandlerMock;
private readonly WireMockServerSettings _settings = new WireMockServerSettings();
mappingMock = new Mock<IMapping>();
public ResponseWithHandlebarsLinqTests()
var filesystemHandlerMock = new Mock<IFileSystemHandler>(MockBehavior.Strict);
filesystemHandlerMock.Setup(fs => fs.ReadResponseBodyAsString(It.IsAny<string>())).Returns("abc");
_settings.FileSystemHandler = filesystemHandlerMock.Object;
}
[Fact]
public async Task Response_ProvideResponse_Handlebars_Linq1_String0()
{
// Assign
var body = new BodyData();
var request = new RequestMessage(new UrlDetails("http://localhost:1234/pathtest"), "POST", "::1", body);
var responseBuilder = Response.Create()
.WithHeader("Content-Type", "application/json")
.WithBodyAsJson(new { x = "{{Linq request.Path 'it'}}" })
.WithTransformer();
// Act
var response = await responseBuilder.ProvideResponseAsync(mappingMock.Object, request, _settings).ConfigureAwait(false);
// Assert
JObject j = JObject.FromObject(response.Message.BodyData.BodyAsJson);
Check.That(j["x"]).IsNotNull();
Check.That(j["x"].ToString()).Equals("/pathtest");
}
[Fact]
public async Task Response_ProvideResponse_Handlebars_Linq1_String1()
{
// Assign
var body = new BodyData
{
_filesystemHandlerMock = new Mock<IFileSystemHandler>(MockBehavior.Strict);
_filesystemHandlerMock.Setup(fs => fs.ReadResponseBodyAsString(It.IsAny<string>())).Returns("abc");
_settings.FileSystemHandler = _filesystemHandlerMock.Object;
}
[Fact]
public async Task Response_ProvideResponse_Handlebars_Linq1_String0()
{
// Assign
var body = new BodyData();
var request = new RequestMessage(new UrlDetails("http://localhost:1234/pathtest"), "POST", "::1", body);
var responseBuilder = Response.Create()
.WithHeader("Content-Type", "application/json")
.WithBodyAsJson(new { x = "{{Linq request.Path 'it'}}" })
.WithTransformer();
// Act
var response = await responseBuilder.ProvideResponseAsync(request, _settings).ConfigureAwait(false);
// Assert
JObject j = JObject.FromObject(response.Message.BodyData.BodyAsJson);
Check.That(j["x"]).IsNotNull();
Check.That(j["x"].ToString()).Equals("/pathtest");
}
[Fact]
public async Task Response_ProvideResponse_Handlebars_Linq1_String1()
{
// Assign
var body = new BodyData
BodyAsJson = new JObject
{
BodyAsJson = new JObject
{
{ "Id", new JValue(9) },
{ "Name", new JValue("Test") }
},
DetectedBodyType = BodyType.Json
};
{ "Id", new JValue(9) },
{ "Name", new JValue("Test") }
},
DetectedBodyType = BodyType.Json
};
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", "::1", body);
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", "::1", body);
var responseBuilder = Response.Create()
.WithHeader("Content-Type", "application/json")
.WithBodyAsJson(new { x = "{{Linq request.bodyAsJson 'it.Name + \"_123\"' }}" })
.WithTransformer();
var responseBuilder = Response.Create()
.WithHeader("Content-Type", "application/json")
.WithBodyAsJson(new { x = "{{Linq request.bodyAsJson 'it.Name + \"_123\"' }}" })
.WithTransformer();
// Act
var response = await responseBuilder.ProvideResponseAsync(request, _settings).ConfigureAwait(false);
// Act
var response = await responseBuilder.ProvideResponseAsync(mappingMock.Object, request, _settings).ConfigureAwait(false);
// Assert
JObject j = JObject.FromObject(response.Message.BodyData.BodyAsJson);
Check.That(j["x"]).IsNotNull();
Check.That(j["x"].ToString()).Equals("Test_123");
}
// Assert
JObject j = JObject.FromObject(response.Message.BodyData.BodyAsJson);
Check.That(j["x"]).IsNotNull();
Check.That(j["x"].ToString()).Equals("Test_123");
}
[Fact]
public async Task Response_ProvideResponse_Handlebars_Linq1_String2()
[Fact]
public async Task Response_ProvideResponse_Handlebars_Linq1_String2()
{
// Assign
var body = new BodyData
{
// Assign
var body = new BodyData
BodyAsJson = new JObject
{
BodyAsJson = new JObject
{
{ "Id", new JValue(9) },
{ "Name", new JValue("Test") }
},
DetectedBodyType = BodyType.Json
};
{ "Id", new JValue(9) },
{ "Name", new JValue("Test") }
},
DetectedBodyType = BodyType.Json
};
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", "::1", body);
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", "::1", body);
var responseBuilder = Response.Create()
.WithHeader("Content-Type", "application/json")
.WithBodyAsJson(new { x = "{{Linq request.bodyAsJson 'new(it.Name + \"_123\" as N, it.Id as I)' }}" })
.WithTransformer();
var responseBuilder = Response.Create()
.WithHeader("Content-Type", "application/json")
.WithBodyAsJson(new { x = "{{Linq request.bodyAsJson 'new(it.Name + \"_123\" as N, it.Id as I)' }}" })
.WithTransformer();
// Act
var response = await responseBuilder.ProvideResponseAsync(request, _settings).ConfigureAwait(false);
// Act
var response = await responseBuilder.ProvideResponseAsync(mappingMock.Object, request, _settings).ConfigureAwait(false);
// Assert
JObject j = JObject.FromObject(response.Message.BodyData.BodyAsJson);
Check.That(j["x"]).IsNotNull();
Check.That(j["x"].ToString()).Equals("{ N = Test_123, I = 9 }");
}
// Assert
JObject j = JObject.FromObject(response.Message.BodyData.BodyAsJson);
Check.That(j["x"]).IsNotNull();
Check.That(j["x"].ToString()).Equals("{ N = Test_123, I = 9 }");
}
[Fact]
public async Task Response_ProvideResponse_Handlebars_Linq2_Object()
[Fact]
public async Task Response_ProvideResponse_Handlebars_Linq2_Object()
{
// Assign
var body = new BodyData
{
// Assign
var body = new BodyData
BodyAsJson = new JObject
{
BodyAsJson = new JObject
{
{ "Id", new JValue(9) },
{ "Name", new JValue("Test") }
},
DetectedBodyType = BodyType.Json
};
{ "Id", new JValue(9) },
{ "Name", new JValue("Test") }
},
DetectedBodyType = BodyType.Json
};
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", "::1", body);
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", "::1", body);
var responseBuilder = Response.Create()
.WithHeader("Content-Type", "application/json")
.WithBodyAsJson(new { x = "{{#Linq request.bodyAsJson 'new(it.Name + \"_123\" as N, it.Id as I)' }}{{this}}{{/Linq}}" })
.WithTransformer();
var responseBuilder = Response.Create()
.WithHeader("Content-Type", "application/json")
.WithBodyAsJson(new { x = "{{#Linq request.bodyAsJson 'new(it.Name + \"_123\" as N, it.Id as I)' }}{{this}}{{/Linq}}" })
.WithTransformer();
// Act
var response = await responseBuilder.ProvideResponseAsync(request, _settings).ConfigureAwait(false);
// Act
var response = await responseBuilder.ProvideResponseAsync(mappingMock.Object, request, _settings).ConfigureAwait(false);
// Assert
JObject j = JObject.FromObject(response.Message.BodyData.BodyAsJson);
Check.That(j["x"]).IsNotNull();
Check.That(j["x"].ToString()).Equals("{ N = Test_123, I = 9 }");
}
// Assert
JObject j = JObject.FromObject(response.Message.BodyData.BodyAsJson);
Check.That(j["x"]).IsNotNull();
Check.That(j["x"].ToString()).Equals("{ N = Test_123, I = 9 }");
}
[Fact]
public void Response_ProvideResponse_Handlebars_Linq_Throws_ArgumentException()
[Fact]
public void Response_ProvideResponse_Handlebars_Linq_Throws_ArgumentException()
{
// Assign
var body = new BodyData
{
// Assign
var body = new BodyData
BodyAsJson = new { x = "x" },
DetectedBodyType = BodyType.Json
};
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", "::1", body);
var responseBuilder = Response.Create()
.WithBodyAsJson(new { x = "{{Linq request.bodyAsJson 1}}" })
.WithTransformer();
// Act
Check.ThatAsyncCode(() => responseBuilder.ProvideResponseAsync(mappingMock.Object, request, _settings)).Throws<ArgumentException>();
}
[Fact]
public void Response_ProvideResponse_Handlebars_Linq1_Throws_ArgumentNullException()
{
// Assign
var body = new BodyData();
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", "::1", body);
var responseBuilder = Response.Create()
.WithBodyAsJson(new { x = "{{Linq request.body 'Name'}}" })
.WithTransformer();
// Act
Check.ThatAsyncCode(() => responseBuilder.ProvideResponseAsync(mappingMock.Object, request, _settings)).Throws<ArgumentNullException>();
}
[Fact]
public void Response_ProvideResponse_Handlebars_Linq1_Throws_HandlebarsException()
{
// Assign
var body = new BodyData();
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", "::1", body);
var responseBuilder = Response.Create()
.WithBodyAsJson(new { x = "{{Linq request.bodyAsJson}} ''" })
.WithTransformer();
// Act
Check.ThatAsyncCode(() => responseBuilder.ProvideResponseAsync(mappingMock.Object, request, _settings)).Throws<HandlebarsException>();
}
[Fact]
public void Response_ProvideResponse_Handlebars_Linq1_ParseError_Throws_ExceptionMessage()
{
// Assign
var body = new BodyData
{
BodyAsJson = new JObject
{
BodyAsJson = new { x = "x" },
DetectedBodyType = BodyType.Json
};
{ "Id", new JValue(9) },
{ "Name", new JValue("Test") }
},
DetectedBodyType = BodyType.Json
};
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", "::1", body);
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", "::1", body);
var responseBuilder = Response.Create()
.WithBodyAsJson(new { x = "{{Linq request.bodyAsJson 1}}" })
.WithTransformer();
var responseBuilder = Response.Create()
.WithBodyAsJson(new { x = "{{Linq request.bodyAsJson '---' }}" })
.WithTransformer();
// Act
Check.ThatAsyncCode(() => responseBuilder.ProvideResponseAsync(request, _settings)).Throws<ArgumentException>();
}
// Act
Func<Task> a = async () => await responseBuilder.ProvideResponseAsync(mappingMock.Object, request, _settings).ConfigureAwait(false);
[Fact]
public void Response_ProvideResponse_Handlebars_Linq1_Throws_ArgumentNullException()
// Assert
a.Should().ThrowAsync<HandlebarsException>();
}
[Fact]
public void Response_ProvideResponse_Handlebars_Linq2_ParseError_Throws_ExceptionMessage()
{
// Assign
var body = new BodyData
{
// Assign
var body = new BodyData();
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", "::1", body);
var responseBuilder = Response.Create()
.WithBodyAsJson(new { x = "{{Linq request.body 'Name'}}" })
.WithTransformer();
// Act
Check.ThatAsyncCode(() => responseBuilder.ProvideResponseAsync(request, _settings)).Throws<ArgumentNullException>();
}
[Fact]
public void Response_ProvideResponse_Handlebars_Linq1_Throws_HandlebarsException()
{
// Assign
var body = new BodyData();
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", "::1", body);
var responseBuilder = Response.Create()
.WithBodyAsJson(new { x = "{{Linq request.bodyAsJson}} ''" })
.WithTransformer();
// Act
Check.ThatAsyncCode(() => responseBuilder.ProvideResponseAsync(request, _settings)).Throws<HandlebarsException>();
}
[Fact]
public void Response_ProvideResponse_Handlebars_Linq1_ParseError_Throws_ExceptionMessage()
{
// Assign
var body = new BodyData
BodyAsJson = new JObject
{
BodyAsJson = new JObject
{
{ "Id", new JValue(9) },
{ "Name", new JValue("Test") }
},
DetectedBodyType = BodyType.Json
};
{ "Id", new JValue(9) },
{ "Name", new JValue("Test") }
},
DetectedBodyType = BodyType.Json
};
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", "::1", body);
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", "::1", body);
var responseBuilder = Response.Create()
.WithBodyAsJson(new { x = "{{Linq request.bodyAsJson '---' }}" })
.WithTransformer();
var responseBuilder = Response.Create()
.WithBodyAsJson(new { x = "{{#Linq request.bodyAsJson '---' }}{{this}}{{/Linq}}" })
.WithTransformer();
// Act
Func<Task> a = async () => await responseBuilder.ProvideResponseAsync(request, _settings).ConfigureAwait(false);
// Act
Func<Task> a = async () => await responseBuilder.ProvideResponseAsync(mappingMock.Object, request, _settings).ConfigureAwait(false);
// Assert
a.Should().ThrowAsync<HandlebarsException>();
}
[Fact]
public void Response_ProvideResponse_Handlebars_Linq2_ParseError_Throws_ExceptionMessage()
{
// Assign
var body = new BodyData
{
BodyAsJson = new JObject
{
{ "Id", new JValue(9) },
{ "Name", new JValue("Test") }
},
DetectedBodyType = BodyType.Json
};
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", "::1", body);
var responseBuilder = Response.Create()
.WithBodyAsJson(new { x = "{{#Linq request.bodyAsJson '---' }}{{this}}{{/Linq}}" })
.WithTransformer();
// Act
Func<Task> a = async () => await responseBuilder.ProvideResponseAsync(request, _settings).ConfigureAwait(false);
// Assert
a.Should().ThrowAsync<HandlebarsException>();
}
// Assert
a.Should().ThrowAsync<HandlebarsException>();
}
}

View File

@@ -10,160 +10,162 @@ using WireMock.Settings;
using WireMock.Types;
using Xunit;
namespace WireMock.Net.Tests.ResponseBuilders
namespace WireMock.Net.Tests.ResponseBuilders;
public class ResponseWithHandlebarsRandomTests
{
public class ResponseWithHandlebarsRandomTests
private const string ClientIp = "::1";
private readonly WireMockServerSettings _settings = new();
private readonly Mock<IMapping> _mappingMock;
public ResponseWithHandlebarsRandomTests()
{
private const string ClientIp = "::1";
_mappingMock = new Mock<IMapping>();
private readonly WireMockServerSettings _settings = new WireMockServerSettings();
var filesystemHandlerMock = new Mock<IFileSystemHandler>(MockBehavior.Strict);
filesystemHandlerMock.Setup(fs => fs.ReadResponseBodyAsString(It.IsAny<string>())).Returns("abc");
public ResponseWithHandlebarsRandomTests()
{
var filesystemHandlerMock = new Mock<IFileSystemHandler>(MockBehavior.Strict);
filesystemHandlerMock.Setup(fs => fs.ReadResponseBodyAsString(It.IsAny<string>())).Returns("abc");
_settings.FileSystemHandler = filesystemHandlerMock.Object;
}
_settings.FileSystemHandler = filesystemHandlerMock.Object;
}
[Fact]
public async Task Response_ProvideResponseAsync_Handlebars_Random1()
{
// Assign
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "GET", ClientIp);
[Fact]
public async Task Response_ProvideResponseAsync_Handlebars_Random1()
{
// Assign
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "GET", ClientIp);
var responseBuilder = Response.Create()
.WithBodyAsJson(new
{
Text = "{{Random Type=\"Text\" Min=8 Max=20}}",
DateTime = "{{Random Type=\"DateTime\"}}",
Integer = "{{Random Type=\"Integer\" Min=1000 Max=1000}}",
Long = "{{Random Type=\"Long\" Min=77777777 Max=99999999}}"
})
.WithTransformer();
var responseBuilder = Response.Create()
.WithBodyAsJson(new
{
Text = "{{Random Type=\"Text\" Min=8 Max=20}}",
DateTime = "{{Random Type=\"DateTime\"}}",
Integer = "{{Random Type=\"Integer\" Min=1000 Max=1000}}",
Long = "{{Random Type=\"Long\" Min=77777777 Max=99999999}}"
})
.WithTransformer();
// Act
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
// Act
var response = await responseBuilder.ProvideResponseAsync(request, _settings).ConfigureAwait(false);
// Assert
JObject j = JObject.FromObject(response.Message.BodyData.BodyAsJson);
Check.That(j["Text"].Value<string>()).IsNotEmpty();
Check.That(j["Integer"].Value<int>()).IsEqualTo(1000);
Check.That(j["Long"].Value<long>()).IsStrictlyGreaterThan(77777777).And.IsStrictlyLessThan(99999999);
}
// Assert
JObject j = JObject.FromObject(response.Message.BodyData.BodyAsJson);
Check.That(j["Text"].Value<string>()).IsNotEmpty();
Check.That(j["Integer"].Value<int>()).IsEqualTo(1000);
Check.That(j["Long"].Value<long>()).IsStrictlyGreaterThan(77777777).And.IsStrictlyLessThan(99999999);
}
[Fact]
public async Task Response_ProvideResponseAsync_Handlebars_Random1_Boolean()
{
// Assign
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "GET", ClientIp);
[Fact]
public async Task Response_ProvideResponseAsync_Handlebars_Random1_Boolean()
{
// Assign
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "GET", ClientIp);
var responseBuilder = Response.Create()
.WithBodyAsJson(new
{
Value = "{{Random Type=\"Boolean\"}}"
})
.WithTransformer();
var responseBuilder = Response.Create()
.WithBodyAsJson(new
{
Value = "{{Random Type=\"Boolean\"}}"
})
.WithTransformer();
// Act
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
// Act
var response = await responseBuilder.ProvideResponseAsync(request, _settings).ConfigureAwait(false);
// Assert
JObject j = JObject.FromObject(response.Message.BodyData.BodyAsJson);
Check.That(j["Value"].Type).IsEqualTo(JTokenType.Boolean);
}
// Assert
JObject j = JObject.FromObject(response.Message.BodyData.BodyAsJson);
Check.That(j["Value"].Type).IsEqualTo(JTokenType.Boolean);
}
[Theory]
[InlineData(ReplaceNodeOptions.None, JTokenType.Integer)]
//[InlineData(ReplaceNodeOptions.Bool, JTokenType.String)]
//[InlineData(ReplaceNodeOptions.Integer, JTokenType.Integer)]
//[InlineData(ReplaceNodeOptions.Bool | ReplaceNodeOptions.Integer, JTokenType.Integer)]
public async Task Response_ProvideResponseAsync_Handlebars_Random1_Integer(ReplaceNodeOptions options, JTokenType expected)
{
// Assign
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "GET", ClientIp);
[Theory]
[InlineData(ReplaceNodeOptions.None, JTokenType.Integer)]
//[InlineData(ReplaceNodeOptions.Bool, JTokenType.String)]
//[InlineData(ReplaceNodeOptions.Integer, JTokenType.Integer)]
//[InlineData(ReplaceNodeOptions.Bool | ReplaceNodeOptions.Integer, JTokenType.Integer)]
public async Task Response_ProvideResponseAsync_Handlebars_Random1_Integer(ReplaceNodeOptions options, JTokenType expected)
{
// Assign
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "GET", ClientIp);
var responseBuilder = Response.Create()
.WithBodyAsJson(new
{
Value = "{{Random Type=\"Integer\"}}"
})
.WithTransformer(options);
var responseBuilder = Response.Create()
.WithBodyAsJson(new
{
Value = "{{Random Type=\"Integer\"}}"
})
.WithTransformer(options);
// Act
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
// Act
var response = await responseBuilder.ProvideResponseAsync(request, _settings).ConfigureAwait(false);
// Assert
JObject j = JObject.FromObject(response.Message.BodyData.BodyAsJson);
Check.That(j["Value"].Type).IsEqualTo(expected);
}
// Assert
JObject j = JObject.FromObject(response.Message.BodyData.BodyAsJson);
Check.That(j["Value"].Type).IsEqualTo(expected);
}
[Fact]
public async Task Response_ProvideResponseAsync_Handlebars_Random1_Guid()
{
// Assign
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "GET", ClientIp);
[Fact]
public async Task Response_ProvideResponseAsync_Handlebars_Random1_Guid()
{
// Assign
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "GET", ClientIp);
var responseBuilder = Response.Create()
.WithBodyAsJson(new
{
Guid1 = "{{Random Type=\"Guid\" Uppercase=false}}",
Guid2 = "{{Random Type=\"Guid\"}}"
})
.WithTransformer();
var responseBuilder = Response.Create()
.WithBodyAsJson(new
{
Guid1 = "{{Random Type=\"Guid\" Uppercase=false}}",
Guid2 = "{{Random Type=\"Guid\"}}"
})
.WithTransformer();
// Act
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
// Act
var response = await responseBuilder.ProvideResponseAsync(request, _settings).ConfigureAwait(false);
// Assert
JObject j = JObject.FromObject(response.Message.BodyData.BodyAsJson);
string guid1 = j["Guid1"].Value<string>();
Check.That(guid1.ToUpper()).IsNotEqualTo(guid1);
string guid2 = j["Guid2"].Value<string>();
Check.That(guid2.ToUpper()).IsEqualTo(guid2);
}
// Assert
JObject j = JObject.FromObject(response.Message.BodyData.BodyAsJson);
string guid1 = j["Guid1"].Value<string>();
Check.That(guid1.ToUpper()).IsNotEqualTo(guid1);
string guid2 = j["Guid2"].Value<string>();
Check.That(guid2.ToUpper()).IsEqualTo(guid2);
}
[Fact]
public async Task Response_ProvideResponseAsync_Handlebars_Random1_StringList()
{
// Assign
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "GET", ClientIp);
[Fact]
public async Task Response_ProvideResponseAsync_Handlebars_Random1_StringList()
{
// Assign
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "GET", ClientIp);
var responseBuilder = Response.Create()
.WithBodyAsJson(new
{
StringValue = "{{Random Type=\"StringList\" Values=[\"a\", \"b\", \"c\"]}}"
})
.WithTransformer();
var responseBuilder = Response.Create()
.WithBodyAsJson(new
{
StringValue = "{{Random Type=\"StringList\" Values=[\"a\", \"b\", \"c\"]}}"
})
.WithTransformer();
// Act
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
// Act
var response = await responseBuilder.ProvideResponseAsync(request, _settings).ConfigureAwait(false);
// Assert
JObject j = JObject.FromObject(response.Message.BodyData.BodyAsJson);
string value = j["StringValue"].Value<string>();
Check.That(new[] { "a", "b", "c" }.Contains(value)).IsTrue();
}
// Assert
JObject j = JObject.FromObject(response.Message.BodyData.BodyAsJson);
string value = j["StringValue"].Value<string>();
Check.That(new[] { "a", "b", "c" }.Contains(value)).IsTrue();
}
[Fact]
public async Task Response_ProvideResponseAsync_Handlebars_Random2()
{
// Assign
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "GET", ClientIp);
[Fact]
public async Task Response_ProvideResponseAsync_Handlebars_Random2()
{
// Assign
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "GET", ClientIp);
var responseBuilder = Response.Create()
.WithBodyAsJson(new
{
Integer = "{{#Random Type=\"Integer\" Min=10000000 Max=99999999}}{{this}}{{/Random}}",
})
.WithTransformer();
var responseBuilder = Response.Create()
.WithBodyAsJson(new
{
Integer = "{{#Random Type=\"Integer\" Min=10000000 Max=99999999}}{{this}}{{/Random}}",
})
.WithTransformer();
// Act
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
// Act
var response = await responseBuilder.ProvideResponseAsync(request, _settings).ConfigureAwait(false);
// Assert
JObject j = JObject.FromObject(response.Message.BodyData.BodyAsJson);
Check.That(j["Integer"].Value<int>()).IsStrictlyGreaterThan(10000000).And.IsStrictlyLessThan(99999999);
}
// Assert
JObject j = JObject.FromObject(response.Message.BodyData.BodyAsJson);
Check.That(j["Integer"].Value<int>()).IsStrictlyGreaterThan(10000000).And.IsStrictlyLessThan(99999999);
}
}

View File

@@ -10,113 +10,114 @@ using WireMock.Types;
using WireMock.Util;
using Xunit;
namespace WireMock.Net.Tests.ResponseBuilders
namespace WireMock.Net.Tests.ResponseBuilders;
public class ResponseWithHandlebarsRegexTests
{
public class ResponseWithHandlebarsRegexTests
private const string ClientIp = "::1";
private readonly WireMockServerSettings _settings = new();
private readonly Mock<IMapping> _mappingMock;
public ResponseWithHandlebarsRegexTests()
{
private const string ClientIp = "::1";
_mappingMock = new Mock<IMapping>();
private readonly Mock<IFileSystemHandler> _filesystemHandlerMock;
private readonly WireMockServerSettings _settings = new WireMockServerSettings();
var filesystemHandlerMock = new Mock<IFileSystemHandler>(MockBehavior.Strict);
filesystemHandlerMock.Setup(fs => fs.ReadResponseBodyAsString(It.IsAny<string>())).Returns("abc");
public ResponseWithHandlebarsRegexTests()
{
_filesystemHandlerMock = new Mock<IFileSystemHandler>(MockBehavior.Strict);
_filesystemHandlerMock.Setup(fs => fs.ReadResponseBodyAsString(It.IsAny<string>())).Returns("abc");
_settings.FileSystemHandler = filesystemHandlerMock.Object;
}
_settings.FileSystemHandler = _filesystemHandlerMock.Object;
}
[Fact]
public async Task Response_ProvideResponseAsync_Handlebars_RegexMatch()
{
// Assign
var body = new BodyData { BodyAsString = "abc", DetectedBodyType = BodyType.String };
[Fact]
public async Task Response_ProvideResponseAsync_Handlebars_RegexMatch()
{
// Assign
var body = new BodyData { BodyAsString = "abc", DetectedBodyType = BodyType.String };
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
var responseBuilder = Response.Create()
.WithBody("{{Regex.Match request.body \"^(\\w+)$\"}}")
.WithTransformer();
var responseBuilder = Response.Create()
.WithBody("{{Regex.Match request.body \"^(\\w+)$\"}}")
.WithTransformer();
// Act
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
// Act
var response = await responseBuilder.ProvideResponseAsync(request, _settings).ConfigureAwait(false);
// assert
Check.That(response.Message.BodyData.BodyAsString).Equals("abc");
}
// assert
Check.That(response.Message.BodyData.BodyAsString).Equals("abc");
}
[Fact]
public async Task Response_ProvideResponseAsync_Handlebars_RegexMatch_NoMatch()
{
// Assign
var body = new BodyData { BodyAsString = "abc", DetectedBodyType = BodyType.String };
[Fact]
public async Task Response_ProvideResponseAsync_Handlebars_RegexMatch_NoMatch()
{
// Assign
var body = new BodyData { BodyAsString = "abc", DetectedBodyType = BodyType.String };
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
var responseBuilder = Response.Create()
.WithBody("{{Regex.Match request.body \"^?0$\"}}")
.WithTransformer();
var responseBuilder = Response.Create()
.WithBody("{{Regex.Match request.body \"^?0$\"}}")
.WithTransformer();
// Act
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
// Act
var response = await responseBuilder.ProvideResponseAsync(request, _settings).ConfigureAwait(false);
// assert
Check.That(response.Message.BodyData.BodyAsString).Equals("");
}
// assert
Check.That(response.Message.BodyData.BodyAsString).Equals("");
}
[Fact]
public async Task Response_ProvideResponseAsync_Handlebars_RegexMatch2()
{
// Assign
var body = new BodyData { BodyAsString = "https://localhost:5000/", DetectedBodyType = BodyType.String };
[Fact]
public async Task Response_ProvideResponseAsync_Handlebars_RegexMatch2()
{
// Assign
var body = new BodyData { BodyAsString = "https://localhost:5000/", DetectedBodyType = BodyType.String };
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
var responseBuilder = Response.Create()
.WithBody("{{#Regex.Match request.body \"^(?<proto>\\w+)://[^/]+?(?<port>\\d+)/?\"}}{{this.port}}-{{this.proto}}{{/Regex.Match}}")
.WithTransformer();
var responseBuilder = Response.Create()
.WithBody("{{#Regex.Match request.body \"^(?<proto>\\w+)://[^/]+?(?<port>\\d+)/?\"}}{{this.port}}-{{this.proto}}{{/Regex.Match}}")
.WithTransformer();
// Act
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
// Act
var response = await responseBuilder.ProvideResponseAsync(request, _settings).ConfigureAwait(false);
// assert
Check.That(response.Message.BodyData.BodyAsString).Equals("5000-https");
}
// assert
Check.That(response.Message.BodyData.BodyAsString).Equals("5000-https");
}
[Fact]
public async Task Response_ProvideResponseAsync_Handlebars_RegexMatch2_NoMatch()
{
// Assign
var body = new BodyData { BodyAsString = "{{\\test", DetectedBodyType = BodyType.String };
[Fact]
public async Task Response_ProvideResponseAsync_Handlebars_RegexMatch2_NoMatch()
{
// Assign
var body = new BodyData { BodyAsString = "{{\\test", DetectedBodyType = BodyType.String };
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
var responseBuilder = Response.Create()
.WithBody("{{#Regex.Match request.body \"^(?<proto>\\w+)://[^/]+?(?<port>\\d+)/?\"}}{{this}}{{/Regex.Match}}")
.WithTransformer();
var responseBuilder = Response.Create()
.WithBody("{{#Regex.Match request.body \"^(?<proto>\\w+)://[^/]+?(?<port>\\d+)/?\"}}{{this}}{{/Regex.Match}}")
.WithTransformer();
// Act
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
// Act
var response = await responseBuilder.ProvideResponseAsync(request, _settings).ConfigureAwait(false);
// assert
Check.That(response.Message.BodyData.BodyAsString).Equals("");
}
// assert
Check.That(response.Message.BodyData.BodyAsString).Equals("");
}
[Fact]
public void Response_ProvideResponseAsync_Handlebars_RegexMatch2_Throws()
{
// Assign
var body = new BodyData { BodyAsString = "{{\\test", DetectedBodyType = BodyType.String };
[Fact]
public void Response_ProvideResponseAsync_Handlebars_RegexMatch2_Throws()
{
// Assign
var body = new BodyData { BodyAsString = "{{\\test", DetectedBodyType = BodyType.String };
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
var responseBuilder = Response.Create()
.WithBody("{{#Regex.Match request.bodyAsJson \"^(?<proto>\\w+)://[^/]+?(?<port>\\d+)/?\"}}{{/Regex.Match}}")
.WithTransformer();
var responseBuilder = Response.Create()
.WithBody("{{#Regex.Match request.bodyAsJson \"^(?<proto>\\w+)://[^/]+?(?<port>\\d+)/?\"}}{{/Regex.Match}}")
.WithTransformer();
// Act and Assert
Check.ThatAsyncCode(() => responseBuilder.ProvideResponseAsync(request, _settings)).Throws<ArgumentNullException>();
}
// Act and Assert
Check.ThatAsyncCode(() => responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings)).Throws<ArgumentNullException>();
}
}

View File

@@ -14,117 +14,119 @@ using FluentAssertions;
using Wmhelp.XPath2;
#endif
namespace WireMock.Net.Tests.ResponseBuilders
namespace WireMock.Net.Tests.ResponseBuilders;
public class ResponseWithHandlebarsXPathTests
{
public class ResponseWithHandlebarsXPathTests
private const string ClientIp = "::1";
private readonly WireMockServerSettings _settings = new();
private readonly Mock<IMapping> _mappingMock;
public ResponseWithHandlebarsXPathTests()
{
private const string ClientIp = "::1";
_mappingMock = new Mock<IMapping>();
private readonly Mock<IFileSystemHandler> _filesystemHandlerMock;
private readonly WireMockServerSettings _settings = new WireMockServerSettings();
var filesystemHandlerMock = new Mock<IFileSystemHandler>(MockBehavior.Strict);
filesystemHandlerMock.Setup(fs => fs.ReadResponseBodyAsString(It.IsAny<string>())).Returns("abc");
public ResponseWithHandlebarsXPathTests()
_settings.FileSystemHandler = filesystemHandlerMock.Object;
}
[Fact]
public async Task Response_ProvideResponse_Handlebars_XPath_SelectSingleNode_Request_BodyAsString()
{
// Assign
var body = new BodyData
{
_filesystemHandlerMock = new Mock<IFileSystemHandler>(MockBehavior.Strict);
_filesystemHandlerMock.Setup(fs => fs.ReadResponseBodyAsString(It.IsAny<string>())).Returns("abc");
_settings.FileSystemHandler = _filesystemHandlerMock.Object;
}
[Fact]
public async Task Response_ProvideResponse_Handlebars_XPath_SelectSingleNode_Request_BodyAsString()
{
// Assign
var body = new BodyData
{
BodyAsString = @"<todo-list>
BodyAsString = @"<todo-list>
<todo-item id='a1'>abc</todo-item>
<todo-item id='a2'>def</todo-item>
<todo-item id='a3'>xyz</todo-item>
</todo-list>",
DetectedBodyType = BodyType.String
};
DetectedBodyType = BodyType.String
};
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
var responseBuilder = Response.Create()
.WithHeader("Content-Type", "application/xml")
.WithBody("<response>{{XPath.SelectSingleNode request.body \"/todo-list/todo-item[1]\"}}</response>")
.WithTransformer();
var responseBuilder = Response.Create()
.WithHeader("Content-Type", "application/xml")
.WithBody("<response>{{XPath.SelectSingleNode request.body \"/todo-list/todo-item[1]\"}}</response>")
.WithTransformer();
// Act
var response = await responseBuilder.ProvideResponseAsync(request, _settings).ConfigureAwait(false);
// Act
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
// Assert
var nav = new XmlDocument { InnerXml = response.Message.BodyData.BodyAsString }.CreateNavigator();
var node = nav.XPath2SelectSingleNode("/response/todo-item");
Check.That(node.Value).Equals("abc");
Check.That(node.GetAttribute("id", "")).Equals("a1");
}
// Assert
var nav = new XmlDocument { InnerXml = response.Message.BodyData.BodyAsString }.CreateNavigator();
var node = nav.XPath2SelectSingleNode("/response/todo-item");
Check.That(node.Value).Equals("abc");
Check.That(node.GetAttribute("id", "")).Equals("a1");
}
[Fact]
public async Task Response_ProvideResponse_Handlebars_XPath_SelectSingleNode_Text_Request_BodyAsString()
[Fact]
public async Task Response_ProvideResponse_Handlebars_XPath_SelectSingleNode_Text_Request_BodyAsString()
{
// Assign
var body = new BodyData
{
// Assign
var body = new BodyData
{
BodyAsString = @"<todo-list>
BodyAsString = @"<todo-list>
<todo-item id='a1'>abc</todo-item>
<todo-item id='a2'>def</todo-item>
<todo-item id='a3'>xyz</todo-item>
</todo-list>",
DetectedBodyType = BodyType.String
};
DetectedBodyType = BodyType.String
};
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
var responseBuilder = Response.Create()
.WithHeader("Content-Type", "application/xml")
.WithBody("{{XPath.SelectSingleNode request.body \"/todo-list/todo-item[1]/text()\"}}")
.WithTransformer();
var responseBuilder = Response.Create()
.WithHeader("Content-Type", "application/xml")
.WithBody("{{XPath.SelectSingleNode request.body \"/todo-list/todo-item[1]/text()\"}}")
.WithTransformer();
// Act
var response = await responseBuilder.ProvideResponseAsync(request, _settings).ConfigureAwait(false);
// Act
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
// Assert
Check.That(response.Message.BodyData.BodyAsString).IsEqualTo("abc");
}
// Assert
Check.That(response.Message.BodyData.BodyAsString).IsEqualTo("abc");
}
[Fact]
public async Task Response_ProvideResponse_Handlebars_XPath_SelectNodes_Request_BodyAsString()
[Fact]
public async Task Response_ProvideResponse_Handlebars_XPath_SelectNodes_Request_BodyAsString()
{
// Assign
var body = new BodyData
{
// Assign
var body = new BodyData
{
BodyAsString = @"<todo-list>
BodyAsString = @"<todo-list>
<todo-item id='a1'>abc</todo-item>
<todo-item id='a2'>def</todo-item>
<todo-item id='a3'>xyz</todo-item>
</todo-list>",
DetectedBodyType = BodyType.String
};
DetectedBodyType = BodyType.String
};
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
var responseBuilder = Response.Create()
.WithHeader("Content-Type", "application/xml")
.WithBody("<response>{{XPath.SelectNodes request.body \"/todo-list/todo-item\"}}</response>")
.WithTransformer();
var responseBuilder = Response.Create()
.WithHeader("Content-Type", "application/xml")
.WithBody("<response>{{XPath.SelectNodes request.body \"/todo-list/todo-item\"}}</response>")
.WithTransformer();
// Act
var response = await responseBuilder.ProvideResponseAsync(request, _settings).ConfigureAwait(false);
// Act
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
// Assert
var nav = new XmlDocument { InnerXml = response.Message.BodyData.BodyAsString }.CreateNavigator();
var nodes = nav.XPath2SelectNodes("/response/todo-item");
Check.That(nodes.Count + 1).IsEqualTo(3);
}
// Assert
var nav = new XmlDocument { InnerXml = response.Message.BodyData.BodyAsString }.CreateNavigator();
var nodes = nav.XPath2SelectNodes("/response/todo-item");
Check.That(nodes.Count + 1).IsEqualTo(3);
}
[Fact]
public async Task Response_ProvideResponse_Handlebars_XPath_SelectSingleNode_Request_SoapXML_BodyAsString()
{
// Assign
string soap = @"
[Fact]
public async Task Response_ProvideResponse_Handlebars_XPath_SelectSingleNode_Request_SoapXML_BodyAsString()
{
// Assign
string soap = @"
<soapenv:Envelope xmlns:soapenv=""http://schemas.xmlsoap.org/soap/envelope/"" xmlns:ns=""http://www.Test.nl/XMLHeader/10"" xmlns:req=""http://www.Test.nl/Betalen/COU/Services/RdplDbTknLystByOvkLyst/8/Req"">
<soapenv:Header>
<ns:TestHeader>
@@ -156,80 +158,79 @@ namespace WireMock.Net.Tests.ResponseBuilders
</req:RdplDbTknLystByOvkLyst_REQ>
</soapenv:Body>
</soapenv:Envelope>";
var body = new BodyData
{
BodyAsString = soap,
DetectedBodyType = BodyType.String
};
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
var responseBuilder = Response.Create()
.WithHeader("Content-Type", "application/xml")
.WithBody("<response>{{XPath.SelectSingleNode request.body \"//*[local-name()='TokenIdLijst']\"}}</response>")
.WithTransformer();
// Act
var response = await responseBuilder.ProvideResponseAsync(request, _settings).ConfigureAwait(false);
// Assert
response.Message.BodyData.BodyAsString.Should().Contain("TokenIdLijst").And.Contain("0000083256").And.Contain("0000083259");
}
[Fact]
public async Task Response_ProvideResponse_Handlebars_XPath_Evaluate_Request_BodyAsString()
var body = new BodyData
{
// Assign
var body = new BodyData
{
BodyAsString = @"<todo-list>
<todo-item id='a1'>abc</todo-item>
<todo-item id='a2'>def</todo-item>
<todo-item id='a3'>xyz</todo-item>
</todo-list>",
DetectedBodyType = BodyType.String
};
BodyAsString = soap,
DetectedBodyType = BodyType.String
};
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
var responseBuilder = Response.Create()
.WithHeader("Content-Type", "application/xml")
.WithBody("{{XPath.Evaluate request.body \"boolean(/todo-list[count(todo-item) = 3])\"}}")
.WithTransformer();
var responseBuilder = Response.Create()
.WithHeader("Content-Type", "application/xml")
.WithBody("<response>{{XPath.SelectSingleNode request.body \"//*[local-name()='TokenIdLijst']\"}}</response>")
.WithTransformer();
// Act
var response = await responseBuilder.ProvideResponseAsync(request, _settings).ConfigureAwait(false);
// Act
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
// Assert
Check.That(response.Message.BodyData.BodyAsString).IsEqualIgnoringCase("True");
}
[Fact]
public async Task Response_ProvideResponse_Handlebars_XPath_Evaluate_Attribute_Request_BodyAsString()
{
// Assign
var body = new BodyData
{
BodyAsString = @"<todo-list>
<todo-item id='a1'>abc</todo-item>
<todo-item id='a2'>def</todo-item>
<todo-item id='a3'>xyz</todo-item>
</todo-list>",
DetectedBodyType = BodyType.String
};
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
var responseBuilder = Response.Create()
.WithHeader("Content-Type", "application/xml")
.WithBody("{{XPath.Evaluate request.body \"string(/todo-list/todo-item[1]/@id)\"}}")
.WithTransformer();
// Act
var response = await responseBuilder.ProvideResponseAsync(request, _settings).ConfigureAwait(false);
// Assert
Check.That(response.Message.BodyData.BodyAsString).IsEqualTo("a1");
}
// Assert
response.Message.BodyData.BodyAsString.Should().Contain("TokenIdLijst").And.Contain("0000083256").And.Contain("0000083259");
}
}
[Fact]
public async Task Response_ProvideResponse_Handlebars_XPath_Evaluate_Request_BodyAsString()
{
// Assign
var body = new BodyData
{
BodyAsString = @"<todo-list>
<todo-item id='a1'>abc</todo-item>
<todo-item id='a2'>def</todo-item>
<todo-item id='a3'>xyz</todo-item>
</todo-list>",
DetectedBodyType = BodyType.String
};
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
var responseBuilder = Response.Create()
.WithHeader("Content-Type", "application/xml")
.WithBody("{{XPath.Evaluate request.body \"boolean(/todo-list[count(todo-item) = 3])\"}}")
.WithTransformer();
// Act
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
// Assert
Check.That(response.Message.BodyData.BodyAsString).IsEqualIgnoringCase("True");
}
[Fact]
public async Task Response_ProvideResponse_Handlebars_XPath_Evaluate_Attribute_Request_BodyAsString()
{
// Assign
var body = new BodyData
{
BodyAsString = @"<todo-list>
<todo-item id='a1'>abc</todo-item>
<todo-item id='a2'>def</todo-item>
<todo-item id='a3'>xyz</todo-item>
</todo-list>",
DetectedBodyType = BodyType.String
};
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
var responseBuilder = Response.Create()
.WithHeader("Content-Type", "application/xml")
.WithBody("{{XPath.Evaluate request.body \"string(/todo-list/todo-item[1]/@id)\"}}")
.WithTransformer();
// Act
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
// Assert
Check.That(response.Message.BodyData.BodyAsString).IsEqualTo("a1");
}
}

View File

@@ -1,4 +1,4 @@
using Moq;
using Moq;
using Newtonsoft.Json.Linq;
using NFluent;
using System.Threading.Tasks;
@@ -8,67 +8,68 @@ using WireMock.ResponseBuilders;
using WireMock.Settings;
using Xunit;
namespace WireMock.Net.Tests.ResponseBuilders
namespace WireMock.Net.Tests.ResponseBuilders;
public class ResponseWithHandlebarsXegerTests
{
public class ResponseWithHandlebarsXegerTests
private const string ClientIp = "::1";
private readonly WireMockServerSettings _settings = new();
private readonly Mock<IMapping> _mappingMock;
public ResponseWithHandlebarsXegerTests()
{
private const string ClientIp = "::1";
_mappingMock = new Mock<IMapping>();
private readonly Mock<IFileSystemHandler> _filesystemHandlerMock;
private readonly WireMockServerSettings _settings = new WireMockServerSettings();
var filesystemHandlerMock = new Mock<IFileSystemHandler>(MockBehavior.Strict);
filesystemHandlerMock.Setup(fs => fs.ReadResponseBodyAsString(It.IsAny<string>())).Returns("abc");
public ResponseWithHandlebarsXegerTests()
{
_filesystemHandlerMock = new Mock<IFileSystemHandler>(MockBehavior.Strict);
_filesystemHandlerMock.Setup(fs => fs.ReadResponseBodyAsString(It.IsAny<string>())).Returns("abc");
_settings.FileSystemHandler = filesystemHandlerMock.Object;
}
_settings.FileSystemHandler = _filesystemHandlerMock.Object;
}
[Fact]
public async Task Response_ProvideResponseAsync_Handlebars_Xeger1()
{
// Assign
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "GET", ClientIp);
[Fact]
public async Task Response_ProvideResponseAsync_Handlebars_Xeger1()
{
// Assign
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "GET", ClientIp);
var responseBuilder = Response.Create()
.WithBodyAsJson(new
{
Number = "{{Xeger.Generate \"[1-9]{1}\\d{3}\"}}",
Postcode = "{{Xeger.Generate \"[1-9][0-9]{3}[A-Z]{2}\"}}"
})
.WithTransformer();
var responseBuilder = Response.Create()
.WithBodyAsJson(new
{
Number = "{{Xeger.Generate \"[1-9]{1}\\d{3}\"}}",
Postcode = "{{Xeger.Generate \"[1-9][0-9]{3}[A-Z]{2}\"}}"
})
.WithTransformer();
// Act
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings);
// Act
var response = await responseBuilder.ProvideResponseAsync(request, _settings);
// Assert
JObject j = JObject.FromObject(response.Message.BodyData.BodyAsJson);
Check.That(j["Number"].Value<int>()).IsStrictlyGreaterThan(1000).And.IsStrictlyLessThan(9999);
Check.That(j["Postcode"].Value<string>()).IsNotEmpty();
}
// Assert
JObject j = JObject.FromObject(response.Message.BodyData.BodyAsJson);
Check.That(j["Number"].Value<int>()).IsStrictlyGreaterThan(1000).And.IsStrictlyLessThan(9999);
Check.That(j["Postcode"].Value<string>()).IsNotEmpty();
}
[Fact]
public async Task Response_ProvideResponseAsync_Handlebars_Xeger2()
{
// Assign
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "GET", ClientIp);
[Fact]
public async Task Response_ProvideResponseAsync_Handlebars_Xeger2()
{
// Assign
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "GET", ClientIp);
var responseBuilder = Response.Create()
.WithBodyAsJson(new
{
Number = "{{#Xeger.Generate \"[1-9]{1}\\d{3}\"}}{{this}}{{/Xeger.Generate}}",
Postcode = "{{#Xeger.Generate \"[1-9][0-9]{3}[A-Z]{2}\"}}{{this}}{{/Xeger.Generate}}"
})
.WithTransformer();
var responseBuilder = Response.Create()
.WithBodyAsJson(new
{
Number = "{{#Xeger.Generate \"[1-9]{1}\\d{3}\"}}{{this}}{{/Xeger.Generate}}",
Postcode = "{{#Xeger.Generate \"[1-9][0-9]{3}[A-Z]{2}\"}}{{this}}{{/Xeger.Generate}}"
})
.WithTransformer();
// Act
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings);
// Act
var response = await responseBuilder.ProvideResponseAsync(request, _settings);
// Assert
JObject j = JObject.FromObject(response.Message.BodyData.BodyAsJson);
Check.That(j["Number"].Value<int>()).IsStrictlyGreaterThan(1000).And.IsStrictlyLessThan(9999);
Check.That(j["Postcode"].Value<string>()).IsNotEmpty();
}
// Assert
JObject j = JObject.FromObject(response.Message.BodyData.BodyAsJson);
Check.That(j["Number"].Value<int>()).IsStrictlyGreaterThan(1000).And.IsStrictlyLessThan(9999);
Check.That(j["Postcode"].Value<string>()).IsNotEmpty();
}
}

View File

@@ -1,5 +1,6 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Moq;
using NFluent;
using WireMock.Models;
using WireMock.ResponseBuilders;
@@ -7,89 +8,95 @@ using WireMock.Settings;
using WireMock.Types;
using Xunit;
namespace WireMock.Net.Tests.ResponseBuilders
namespace WireMock.Net.Tests.ResponseBuilders;
public class ResponseWithHeadersTests
{
public class ResponseWithHeadersTests
private readonly WireMockServerSettings _settings = new();
private const string ClientIp = "::1";
private readonly Mock<IMapping> _mappingMock;
public ResponseWithHeadersTests()
{
private readonly WireMockServerSettings _settings = new WireMockServerSettings();
private const string ClientIp = "::1";
_mappingMock = new Mock<IMapping>();
}
[Theory]
[InlineData("Content-Length", "1024")]
[InlineData("Transfer-Encoding", "identity")]
[InlineData("Location", "http://test")]
public async Task Response_ProvideResponse_WithHeader_SingleValue(string headerName, string headerValue)
{
// Assign
var requestMock = new RequestMessage(new UrlDetails("http://localhost/foo"), "PUT", ClientIp);
IResponseBuilder builder = Response.Create().WithHeader(headerName, headerValue);
[Theory]
[InlineData("Content-Length", "1024")]
[InlineData("Transfer-Encoding", "identity")]
[InlineData("Location", "http://test")]
public async Task Response_ProvideResponse_WithHeader_SingleValue(string headerName, string headerValue)
{
// Assign
var requestMock = new RequestMessage(new UrlDetails("http://localhost/foo"), "PUT", ClientIp);
IResponseBuilder builder = Response.Create().WithHeader(headerName, headerValue);
// Act
var response = await builder.ProvideResponseAsync(requestMock, _settings).ConfigureAwait(false);
// Act
var response = await builder.ProvideResponseAsync(_mappingMock.Object, requestMock, _settings).ConfigureAwait(false);
// Assert
Check.That(response.Message.Headers[headerName].ToString()).Equals(headerValue);
}
// Assert
Check.That(response.Message.Headers[headerName].ToString()).Equals(headerValue);
}
[Theory]
[InlineData("Test", new[] { "one" })]
[InlineData("Test", new[] { "a", "b" })]
public async Task Response_ProvideResponse_WithHeader_MultipleValues(string headerName, string[] headerValues)
{
// Assign
var requestMock = new RequestMessage(new UrlDetails("http://localhost/foo"), "PUT", ClientIp);
IResponseBuilder builder = Response.Create().WithHeader(headerName, headerValues);
[Theory]
[InlineData("Test", new[] { "one" })]
[InlineData("Test", new[] { "a", "b" })]
public async Task Response_ProvideResponse_WithHeader_MultipleValues(string headerName, string[] headerValues)
{
// Assign
var requestMock = new RequestMessage(new UrlDetails("http://localhost/foo"), "PUT", ClientIp);
IResponseBuilder builder = Response.Create().WithHeader(headerName, headerValues);
// Act
var response = await builder.ProvideResponseAsync(requestMock, _settings).ConfigureAwait(false);
// Act
var response = await builder.ProvideResponseAsync(_mappingMock.Object, requestMock, _settings).ConfigureAwait(false);
// Assert
Check.That(response.Message.Headers[headerName].ToArray()).Equals(headerValues);
}
// Assert
Check.That(response.Message.Headers[headerName].ToArray()).Equals(headerValues);
}
[Fact]
public async Task Response_ProvideResponse_WithHeaders_SingleValue()
{
// Assign
var request = new RequestMessage(new UrlDetails("http://localhost"), "GET", ClientIp);
var headers = new Dictionary<string, string> { { "h", "x" } };
var response = Response.Create().WithHeaders(headers);
[Fact]
public async Task Response_ProvideResponse_WithHeaders_SingleValue()
{
// Assign
var request = new RequestMessage(new UrlDetails("http://localhost"), "GET", ClientIp);
var headers = new Dictionary<string, string> { { "h", "x" } };
var response = Response.Create().WithHeaders(headers);
// Act
var responseMessage = await response.ProvideResponseAsync(request, _settings).ConfigureAwait(false);
// Act
var responseMessage = await response.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
// Assert
Check.That(responseMessage.Message.Headers["h"]).ContainsExactly("x");
}
// Assert
Check.That(responseMessage.Message.Headers["h"]).ContainsExactly("x");
}
[Fact]
public async Task Response_ProvideResponse_WithHeaders_MultipleValues()
{
// Assign
var request = new RequestMessage(new UrlDetails("http://localhost"), "GET", ClientIp);
var headers = new Dictionary<string, string[]> { { "h", new[] { "x" } } };
var responseBuilder = Response.Create().WithHeaders(headers);
[Fact]
public async Task Response_ProvideResponse_WithHeaders_MultipleValues()
{
// Assign
var request = new RequestMessage(new UrlDetails("http://localhost"), "GET", ClientIp);
var headers = new Dictionary<string, string[]> { { "h", new[] { "x" } } };
var responseBuilder = Response.Create().WithHeaders(headers);
// Act
var response = await responseBuilder.ProvideResponseAsync(request, _settings).ConfigureAwait(false);
// Act
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
// Assert
Check.That(response.Message.Headers["h"]).ContainsExactly("x");
}
// Assert
Check.That(response.Message.Headers["h"]).ContainsExactly("x");
}
[Fact]
public async Task Response_ProvideResponse_WithHeaders_WiremockList()
{
// Assign
var request = new RequestMessage(new UrlDetails("http://localhost"), "GET", ClientIp);
var headers = new Dictionary<string, WireMockList<string>> { { "h", new WireMockList<string>("x") } };
var builder = Response.Create().WithHeaders(headers);
[Fact]
public async Task Response_ProvideResponse_WithHeaders_WiremockList()
{
// Assign
var request = new RequestMessage(new UrlDetails("http://localhost"), "GET", ClientIp);
var headers = new Dictionary<string, WireMockList<string>> { { "h", new WireMockList<string>("x") } };
var builder = Response.Create().WithHeaders(headers);
// Act
var response = await builder.ProvideResponseAsync(request, _settings).ConfigureAwait(false);
// Act
var response = await builder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
// Assert
Check.That(response.Message.Headers["h"]).ContainsExactly("x");
}
// Assert
Check.That(response.Message.Headers["h"]).ContainsExactly("x");
}
}

View File

@@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;
using Moq;
using NFluent;
using WireMock.Models;
using WireMock.RequestBuilders;
@@ -12,78 +13,81 @@ using WireMock.Types;
using WireMock.Util;
using Xunit;
namespace WireMock.Net.Tests.ResponseBuilders
namespace WireMock.Net.Tests.ResponseBuilders;
public class ResponseWithProxyTests : IDisposable
{
public class ResponseWithProxyTests : IDisposable
private const string ClientIp = "::1";
private readonly WireMockServerSettings _settings = new();
private readonly WireMockServer _server;
private readonly Guid _guid;
private readonly Mock<IMapping> _mappingMock;
public ResponseWithProxyTests()
{
private const string ClientIp = "::1";
private readonly WireMockServerSettings _settings = new WireMockServerSettings();
private readonly WireMockServer _server;
private readonly Guid _guid;
_mappingMock = new Mock<IMapping>();
public ResponseWithProxyTests()
_guid = Guid.NewGuid();
_server = WireMockServer.Start();
_server.Given(Request.Create().UsingPost().WithPath($"/{_guid}"))
.RespondWith(Response.Create().WithStatusCode(201).WithBodyAsJson(new { p = 42 }).WithHeader("Content-Type", "application/json"));
_server.Given(Request.Create().UsingPost().WithPath($"/{_guid}/append"))
.RespondWith(Response.Create().WithStatusCode(201).WithBodyAsJson(new { p = 10 }).WithHeader("Content-Type", "application/json"));
_server.Given(Request.Create().UsingPost().WithPath($"/prepend/{_guid}"))
.RespondWith(Response.Create().WithStatusCode(201).WithBodyAsJson(new { p = 11 }).WithHeader("Content-Type", "application/json"));
_server.Given(Request.Create().UsingPost().WithPath($"/prepend/{_guid}/append"))
.RespondWith(Response.Create().WithStatusCode(201).WithBodyAsJson(new { p = 12 }).WithHeader("Content-Type", "application/json"));
}
[Theory]
[InlineData("", "", "{\"p\":42}")]
[InlineData("", "/append", "{\"p\":10}")]
[InlineData("/prepend", "", "{\"p\":11}")]
[InlineData("/prepend", "/append", "{\"p\":12}")]
public async Task Response_WithProxy(string prepend, string append, string expectedBody)
{
// Assign
var headers = new Dictionary<string, string[]> { { "Content-Type", new[] { "application/xml" } } };
var request = new RequestMessage(new UrlDetails($"{_server.Urls[0]}{prepend}/{_guid}{append}"), "POST", ClientIp, new BodyData { DetectedBodyType = BodyType.Json, BodyAsJson = new { a = 1 } }, headers);
var responseBuilder = Response.Create().WithProxy(_server.Urls[0]);
// Act
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
// Assert
Check.That(request.ProxyUrl).IsNotNull();
Check.That(response.Message.BodyData.BodyAsString).IsEqualTo(expectedBody);
Check.That(response.Message.StatusCode).IsEqualTo(201);
Check.That(response.Message.Headers["Content-Type"].ToString()).IsEqualTo("application/json");
}
[Fact]
public void Response_WithProxy_WebProxySettings()
{
// Assign
var settings = new ProxyAndRecordSettings
{
_guid = Guid.NewGuid();
_server = WireMockServer.Start();
_server.Given(Request.Create().UsingPost().WithPath($"/{_guid}"))
.RespondWith(Response.Create().WithStatusCode(201).WithBodyAsJson(new { p = 42 }).WithHeader("Content-Type", "application/json"));
_server.Given(Request.Create().UsingPost().WithPath($"/{_guid}/append"))
.RespondWith(Response.Create().WithStatusCode(201).WithBodyAsJson(new { p = 10 }).WithHeader("Content-Type", "application/json"));
_server.Given(Request.Create().UsingPost().WithPath($"/prepend/{_guid}"))
.RespondWith(Response.Create().WithStatusCode(201).WithBodyAsJson(new { p = 11 }).WithHeader("Content-Type", "application/json"));
_server.Given(Request.Create().UsingPost().WithPath($"/prepend/{_guid}/append"))
.RespondWith(Response.Create().WithStatusCode(201).WithBodyAsJson(new { p = 12 }).WithHeader("Content-Type", "application/json"));
}
[Theory]
[InlineData("", "", "{\"p\":42}")]
[InlineData("", "/append", "{\"p\":10}")]
[InlineData("/prepend", "", "{\"p\":11}")]
[InlineData("/prepend", "/append", "{\"p\":12}")]
public async Task Response_WithProxy(string prepend, string append, string expectedBody)
{
// Assign
var headers = new Dictionary<string, string[]> { { "Content-Type", new[] { "application/xml" } } };
var request = new RequestMessage(new UrlDetails($"{_server.Urls[0]}{prepend}/{_guid}{append}"), "POST", ClientIp, new BodyData { DetectedBodyType = BodyType.Json, BodyAsJson = new { a = 1 } }, headers);
var responseBuilder = Response.Create().WithProxy(_server.Urls[0]);
// Act
var response = await responseBuilder.ProvideResponseAsync(request, _settings).ConfigureAwait(false);
// Assert
Check.That(request.ProxyUrl).IsNotNull();
Check.That(response.Message.BodyData.BodyAsString).IsEqualTo(expectedBody);
Check.That(response.Message.StatusCode).IsEqualTo(201);
Check.That(response.Message.Headers["Content-Type"].ToString()).IsEqualTo("application/json");
}
[Fact]
public void Response_WithProxy_WebProxySettings()
{
// Assign
var settings = new ProxyAndRecordSettings
Url = "http://test.nl",
WebProxySettings = new WebProxySettings
{
Url = "http://test.nl",
WebProxySettings = new WebProxySettings
{
Address = "http://company",
UserName = "x",
Password = "y"
}
};
var responseBuilder = Response.Create().WithProxy(settings);
Address = "http://company",
UserName = "x",
Password = "y"
}
};
var responseBuilder = Response.Create().WithProxy(settings);
// Act
var request = new RequestMessage(new UrlDetails($"{_server.Urls[0]}/{_guid}"), "GET", ClientIp);
// Act
var request = new RequestMessage(new UrlDetails($"{_server.Urls[0]}/{_guid}"), "GET", ClientIp);
Check.ThatAsyncCode(() => responseBuilder.ProvideResponseAsync(request, _settings)).Throws<HttpRequestException>();
}
Check.ThatAsyncCode(() => responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings)).Throws<HttpRequestException>();
}
public void Dispose()
{
_server?.Stop();
_server?.Dispose();
}
public void Dispose()
{
_server?.Stop();
_server?.Dispose();
}
}

View File

@@ -16,59 +16,60 @@ using Microsoft.Owin;
using Microsoft.AspNetCore.Http;
#endif
namespace WireMock.Net.Tests.ResponseBuilders
namespace WireMock.Net.Tests.ResponseBuilders;
public class ResponseWithScribanTests
{
public class ResponseWithScribanTests
private const string ClientIp = "::1";
private readonly WireMockServerSettings _settings = new();
private readonly Mock<IMapping> _mappingMock;
public ResponseWithScribanTests()
{
private const string ClientIp = "::1";
_mappingMock = new Mock<IMapping>();
private readonly Mock<IFileSystemHandler> _filesystemHandlerMock;
private readonly WireMockServerSettings _settings = new WireMockServerSettings();
var filesystemHandlerMock = new Mock<IFileSystemHandler>(MockBehavior.Strict);
filesystemHandlerMock.Setup(fs => fs.ReadResponseBodyAsString(It.IsAny<string>())).Returns("abc");
public ResponseWithScribanTests()
{
_filesystemHandlerMock = new Mock<IFileSystemHandler>(MockBehavior.Strict);
_filesystemHandlerMock.Setup(fs => fs.ReadResponseBodyAsString(It.IsAny<string>())).Returns("abc");
_settings.FileSystemHandler = _filesystemHandlerMock.Object;
}
[Fact]
public async Task Response_ProvideResponse_DotLiquid_WithNullBody_ShouldNotThrowException()
{
// Assign
var urlDetails = UrlUtils.Parse(new Uri("http://localhost/wiremock/a/b"), new PathString("/wiremock"));
var request = new RequestMessage(urlDetails, "GET", ClientIp);
var responseBuilder = Response.Create().WithTransformer(TransformerType.ScribanDotLiquid);
// Act
var response = await responseBuilder.ProvideResponseAsync(request, _settings).ConfigureAwait(false);
// Assert
response.Message.BodyData.Should().BeNull();
}
[Fact]
public async Task Response_ProvideResponse_DotLiquid_UrlPathVerb()
{
// Assign
var body = new BodyData
{
BodyAsString = "whatever",
DetectedBodyType = BodyType.String
};
var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "POSt", ClientIp, body);
var responseBuilder = Response.Create()
.WithBody("test {{request.Url}} {{request.Path}} {{request.Method}}")
.WithTransformer(TransformerType.Scriban);
// Act
var response = await responseBuilder.ProvideResponseAsync(request, _settings).ConfigureAwait(false);
// Assert
Check.That(response.Message.BodyData.BodyAsString).Equals("test http://localhost/foo /foo POSt");
}
_settings.FileSystemHandler = filesystemHandlerMock.Object;
}
}
[Fact]
public async Task Response_ProvideResponse_DotLiquid_WithNullBody_ShouldNotThrowException()
{
// Assign
var urlDetails = UrlUtils.Parse(new Uri("http://localhost/wiremock/a/b"), new PathString("/wiremock"));
var request = new RequestMessage(urlDetails, "GET", ClientIp);
var responseBuilder = Response.Create().WithTransformer(TransformerType.ScribanDotLiquid);
// Act
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
// Assert
response.Message.BodyData.Should().BeNull();
}
[Fact]
public async Task Response_ProvideResponse_DotLiquid_UrlPathVerb()
{
// Assign
var body = new BodyData
{
BodyAsString = "whatever",
DetectedBodyType = BodyType.String
};
var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "POSt", ClientIp, body);
var responseBuilder = Response.Create()
.WithBody("test {{request.Url}} {{request.Path}} {{request.Method}}")
.WithTransformer(TransformerType.Scriban);
// Act
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
// Assert
Check.That(response.Message.BodyData.BodyAsString).Equals("test http://localhost/foo /foo POSt");
}
}

View File

@@ -7,43 +7,42 @@ using WireMock.ResponseBuilders;
using WireMock.Settings;
using Xunit;
namespace WireMock.Net.Tests.ResponseBuilders
namespace WireMock.Net.Tests.ResponseBuilders;
public class ResponseWithStatusCodeTests
{
public class ResponseWithStatusCodeTests
private readonly Mock<WireMockServerSettings> _settingsMock = new();
private const string ClientIp = "::1";
[Theory]
[InlineData("201", "201")]
[InlineData(201, 201)]
[InlineData(HttpStatusCode.Created, 201)]
public async Task Response_ProvideResponse_WithStatusCode(object statusCode, object expectedStatusCode)
{
private readonly Mock<WireMockServerSettings> _settingsMock = new Mock<WireMockServerSettings>();
private const string ClientIp = "::1";
// Arrange
var request = new RequestMessage(new UrlDetails("http://localhost/fault"), "GET", ClientIp);
[Theory]
[InlineData("201", "201")]
[InlineData(201, 201)]
[InlineData(HttpStatusCode.Created, 201)]
public async Task Response_ProvideResponse_WithStatusCode(object statusCode, object expectedStatusCode)
// Act
var responseBuilder = Response.Create();
switch (statusCode)
{
// Arrange
var request = new RequestMessage(new UrlDetails("http://localhost/fault"), "GET", ClientIp);
case string statusCodeAsString:
responseBuilder = responseBuilder.WithStatusCode(statusCodeAsString);
break;
// Act
var responseBuilder = Response.Create();
switch (statusCode)
{
case string statusCodeAsString:
responseBuilder = responseBuilder.WithStatusCode(statusCodeAsString);
break;
case int statusCodeAInteger:
responseBuilder = responseBuilder.WithStatusCode(statusCodeAInteger);
break;
case int statusCodeAInteger:
responseBuilder = responseBuilder.WithStatusCode(statusCodeAInteger);
break;
case HttpStatusCode statusCodeAsEnum:
responseBuilder = responseBuilder.WithStatusCode(statusCodeAsEnum);
break;
}
var response = await responseBuilder.ProvideResponseAsync(request, _settingsMock.Object).ConfigureAwait(false);
// Assert
response.Message.StatusCode.Should().Be(expectedStatusCode);
case HttpStatusCode statusCodeAsEnum:
responseBuilder = responseBuilder.WithStatusCode(statusCodeAsEnum);
break;
}
var response = await responseBuilder.ProvideResponseAsync(new Mock<IMapping>().Object, request, _settingsMock.Object).ConfigureAwait(false);
// Assert
response.Message.StatusCode.Should().Be(expectedStatusCode);
}
}
}

View File

@@ -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<string, WireMockList<string>>
{
Url = "https://test.com",
Headers = new Dictionary<string, WireMockList<string>>
{
{ "Single", new WireMockList<string>("x") },
{ "Multi", new WireMockList<string>("a", "b") }
},
Method = "post",
BodyData = new BodyData
{
BodyAsString = "b",
DetectedBodyType = BodyType.String,
DetectedBodyTypeFromContentType = BodyType.String
}
{ "Single", new WireMockList<string>("x") },
{ "Multi", new WireMockList<string>("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<string, WireMockList<string>>
{
{ "One", new WireMockList<string>("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<string, WireMockList<string>>
{
{ "First", new WireMockList<string>("x") },
{ "Second", new WireMockList<string>("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<string, WireMockList<string>>
{
{ "One", new WireMockList<string>("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<string, WireMockList<string>>
{
{ "First", new WireMockList<string>("x") },
{ "Second", new WireMockList<string>("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);
}
}

View File

@@ -0,0 +1,70 @@
using System;
using Moq;
using Newtonsoft.Json;
using System.IO;
using FluentAssertions;
using WireMock.Matchers;
using WireMock.RequestBuilders;
using WireMock.Serialization;
using WireMock.Settings;
using WireMock.Util;
using Xunit;
namespace WireMock.Net.Tests.Serialization;
public class ProxyMappingConverterTests
{
private readonly WireMockServerSettings _settings = new();
private readonly MappingConverter _mappingConverter;
private readonly ProxyMappingConverter _sut;
public ProxyMappingConverterTests()
{
var guidUtilsMock = new Mock<IGuidUtils>();
guidUtilsMock.Setup(g => g.NewGuid()).Returns(Guid.Parse("ff55ac0a-fea9-4d7b-be74-5e483a2c1305"));
_mappingConverter = new MappingConverter(new MatcherMapper(_settings));
_sut = new ProxyMappingConverter(_settings, guidUtilsMock.Object);
}
[Fact]
public void ToMapping_UseDefinedRequestMatchers_True()
{
// Arrange
var proxyAndRecordSettings = new ProxyAndRecordSettings
{
UseDefinedRequestMatchers = true
};
var request = Request.Create()
.UsingPost()
.WithPath("x")
.WithParam("p1", "p1-v")
.WithParam("p2", "p2-v")
.WithHeader("Content-Type", new ContentTypeMatcher("text/plain"))
.WithCookie("c", "x")
.WithBody(new RegexMatcher("<RequestType>Auth</RequestType"));
var mappingMock = new Mock<IMapping>();
mappingMock.SetupGet(m => m.RequestMatcher).Returns(request);
mappingMock.SetupGet(m => m.Title).Returns("my title");
mappingMock.SetupGet(m => m.Description).Returns("my description");
var requestMessageMock = new Mock<IRequestMessage>();
var responseMessage = new ResponseMessage();
// Act
var proxyMapping = _sut.ToMapping(mappingMock.Object, proxyAndRecordSettings, requestMessageMock.Object, responseMessage);
// Assert
var model = _mappingConverter.ToMappingModel(proxyMapping);
var json = JsonConvert.SerializeObject(model, JsonSerializationConstants.JsonSerializerSettingsDefault);
var expected = File.ReadAllText(Path.Combine("../../../", "Serialization", "files", "proxy.json"));
json.Should().Be(expected);
}
}

View File

@@ -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<string, string>
{
Url = "https://localhost",
Method = "get",
Headers = new Dictionary<string, string>
{
{ "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<string, string>
{
{ "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<string, string>
{
{ "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<string, string>
{
{ "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<string, string>
{
{ "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<string, WireMockList<string>>
{
{ "x", new WireMockList<string>("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);
}
}

View File

@@ -0,0 +1,72 @@
{
"Guid": "ff55ac0a-fea9-4d7b-be74-5e483a2c1305",
"Title": "my title",
"Description": "my description",
"Priority": -2000000,
"Request": {
"Path": {
"Matchers": [
{
"Name": "WildcardMatcher",
"Pattern": "x",
"IgnoreCase": false
}
]
},
"Methods": [
"POST"
],
"Headers": [
{
"Name": "Content-Type",
"Matchers": [
{
"Name": "ContentTypeMatcher",
"Pattern": "text/plain",
"IgnoreCase": false
}
]
}
],
"Cookies": [
{
"Name": "c",
"Matchers": [
{
"Name": "WildcardMatcher",
"Pattern": "x",
"IgnoreCase": true
}
]
}
],
"Params": [
{
"Name": "p1",
"Matchers": [
{
"Name": "ExactMatcher",
"Pattern": "p1-v"
}
]
},
{
"Name": "p2",
"Matchers": [
{
"Name": "ExactMatcher",
"Pattern": "p2-v"
}
]
}
],
"Body": {
"Matcher": {
"Name": "RegexMatcher",
"Pattern": "<RequestType>Auth</RequestType",
"IgnoreCase": false
}
}
},
"Response": {}
}

View File

@@ -85,6 +85,9 @@
<None Update="responsebody.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Serialization\files\proxy.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="__admin\mappings.org\*.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
@@ -105,6 +108,7 @@
<ItemGroup>
<Folder Include="Pact\files\" />
<Folder Include="Serialization\files\" />
</ItemGroup>
</Project>

View File

@@ -1,3 +1,6 @@
using FluentAssertions;
using Moq;
using NFluent;
using System;
using System.Linq;
using System.Net;
@@ -5,11 +8,9 @@ using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using FluentAssertions;
using Moq;
using NFluent;
using WireMock.Admin.Mappings;
using WireMock.Constants;
using WireMock.Handlers;
using WireMock.Matchers;
using WireMock.Matchers.Request;
using WireMock.RequestBuilders;
using WireMock.ResponseBuilders;
@@ -119,6 +120,61 @@ public class WireMockServerProxyTests
server.Mappings.Should().HaveCount(28);
}
[Fact]
public async Task WireMockServer_Proxy_With_SaveMappingToFile_Is_True_ShouldSaveMappingToFile()
{
// Assign
string path = $"/prx_{Guid.NewGuid()}";
var title = "IndexFile";
var description = "IndexFile_Test";
var stringBody = "<pretendXml>value</pretendXml>";
var serverForProxyForwarding = WireMockServer.Start();
var fileSystemHandlerMock = new Mock<IFileSystemHandler>();
fileSystemHandlerMock.Setup(f => f.GetMappingFolder()).Returns("m");
var settings = new WireMockServerSettings
{
ProxyAndRecordSettings = new ProxyAndRecordSettings
{
Url = serverForProxyForwarding.Urls[0],
SaveMapping = false,
SaveMappingToFile = true
},
FileSystemHandler = fileSystemHandlerMock.Object
};
var server = WireMockServer.Start(settings);
server.Given(Request.Create()
.WithPath("/*")
.WithBody(new RegexMatcher(stringBody)))
.WithTitle(title)
.WithDescription(description)
.AtPriority(WireMockConstants.ProxyPriority)
.RespondWith(Response.Create().WithProxy(new ProxyAndRecordSettings
{
Url = serverForProxyForwarding.Urls[0],
SaveMapping = false,
SaveMappingToFile = true,
UseDefinedRequestMatchers = true,
}));
// Act
var requestMessage = new HttpRequestMessage
{
Method = HttpMethod.Post,
RequestUri = new Uri($"{server.Urls[0]}{path}"),
Content = new StringContent(stringBody)
};
var httpClientHandler = new HttpClientHandler { AllowAutoRedirect = false };
await new HttpClient(httpClientHandler).SendAsync(requestMessage).ConfigureAwait(false);
// Assert
server.Mappings.Should().HaveCount(2);
// Verify
fileSystemHandlerMock.Verify(f => f.WriteMappingFile($"m{System.IO.Path.DirectorySeparatorChar}{title}.json", It.IsRegex(stringBody)), Times.Once);
}
[Fact]
public async Task WireMockServer_Proxy_With_SaveMapping_Is_False_And_SaveMappingToFile_Is_True_ShouldSaveMappingToFile()
{
@@ -735,8 +791,6 @@ public class WireMockServerProxyTests
content.Should().NotBeEmpty();
server.LogEntries.Should().HaveCount(1);
var status = ((StatusModel)server.LogEntries.First().ResponseMessage.BodyData.BodyAsJson).Status;
server.Stop();
}
}