mirror of
https://github.com/wiremock/WireMock.Net.git
synced 2026-01-11 22:30:41 +01:00
Compare commits
41 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
19dd9e113e | ||
|
|
cb09d65f10 | ||
|
|
1402e14621 | ||
|
|
7201479439 | ||
|
|
af46a490a5 | ||
|
|
c02b7ea5dc | ||
|
|
1db2bc7c89 | ||
|
|
4bcc27ff01 | ||
|
|
93682c9bbf | ||
|
|
653e03fcd9 | ||
|
|
06576ab317 | ||
|
|
55a0a6ee71 | ||
|
|
0ce26ab1a0 | ||
|
|
7a4814e335 | ||
|
|
561bb75f9f | ||
|
|
f764881622 | ||
|
|
fdc433f0ce | ||
|
|
c76bb94b4c | ||
|
|
d7b6e03cb2 | ||
|
|
9031541b91 | ||
|
|
bd030594d5 | ||
|
|
eed73ee8b3 | ||
|
|
8476e3c47f | ||
|
|
a7fbc051c9 | ||
|
|
6e45255c9e | ||
|
|
96e68ae2a0 | ||
|
|
b151a581cc | ||
|
|
fdb58b757b | ||
|
|
dd115a69b7 | ||
|
|
12444cc11e | ||
|
|
6c32b9c31a | ||
|
|
3d845d5be5 | ||
|
|
409d55350f | ||
|
|
e7ac620721 | ||
|
|
ceb6596823 | ||
|
|
47e599214f | ||
|
|
b99e300acf | ||
|
|
482b05fc4a | ||
|
|
9e123fbbea | ||
|
|
658f74ac61 | ||
|
|
1392119f9d |
87
CHANGELOG.md
87
CHANGELOG.md
@@ -1,3 +1,90 @@
|
||||
# 1.0.25.0 (23 July 2019)
|
||||
- [#304](https://github.com/WireMock-Net/WireMock.Net/pull/304) - Support WithBody with multiple matchers [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#303](https://github.com/WireMock-Net/WireMock.Net/issues/303) - Question: WithBody can't be used with multiple matching rules? [question]
|
||||
|
||||
# 1.0.24.0 (22 July 2019)
|
||||
- [#302](https://github.com/WireMock-Net/WireMock.Net/pull/302) - Fixed bug 301 by not setting BodyAsFile to null after first use [bug] contributed by [rwwilden](https://github.com/rwwilden)
|
||||
- [#299](https://github.com/WireMock-Net/WireMock.Net/issues/299) - Get Mappings models instead of just IMapping interface [feature, question]
|
||||
- [#300](https://github.com/WireMock-Net/WireMock.Net/issues/300) - Integration with Azure Function [question]
|
||||
- [#301](https://github.com/WireMock-Net/WireMock.Net/issues/301) - Error thrown when calling mocked endpoint second time when using file-based response body [bug]
|
||||
|
||||
# 1.0.23.0 (16 July 2019)
|
||||
- [#298](https://github.com/WireMock-Net/WireMock.Net/pull/298) - MappingModels [feature] contributed by [StefH](https://github.com/StefH)
|
||||
|
||||
# 1.0.22.0 (15 July 2019)
|
||||
- [#297](https://github.com/WireMock-Net/WireMock.Net/pull/297) - FixNullRef (#295) contributed by [StefH](https://github.com/StefH)
|
||||
- [#178](https://github.com/WireMock-Net/WireMock.Net/issues/178) - Bug: Path matching fails when the URL contains encoded parts [bug, question]
|
||||
- [#295](https://github.com/WireMock-Net/WireMock.Net/issues/295) - NullRef in 1.0.21 [bug]
|
||||
- [#296](https://github.com/WireMock-Net/WireMock.Net/issues/296) - url param - how to accept either of multiple values [question]
|
||||
|
||||
# 1.0.21.0 (03 July 2019)
|
||||
- [#286](https://github.com/WireMock-Net/WireMock.Net/pull/286) - Handlebars Extension [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#293](https://github.com/WireMock-Net/WireMock.Net/pull/293) - workaround for AppContext.BaseDirectory being null on some platforms contributed by [eli-darkly](https://github.com/eli-darkly)
|
||||
- [#294](https://github.com/WireMock-Net/WireMock.Net/pull/294) - don't strip request body if we don't recognize the request method contributed by [eli-darkly](https://github.com/eli-darkly)
|
||||
- [#275](https://github.com/WireMock-Net/WireMock.Net/issues/275) - Server not starting up with 1.0.15 code [invalid, question]
|
||||
- [#280](https://github.com/WireMock-Net/WireMock.Net/issues/280) - Static Mapping Not work [question]
|
||||
- [#285](https://github.com/WireMock-Net/WireMock.Net/issues/285) - Need ability to add custom ResponseMessageTransformers [feature, question]
|
||||
- [#288](https://github.com/WireMock-Net/WireMock.Net/issues/288) - Allow setting root folder in LocalFileSystemHandler [feature, question]
|
||||
- [#289](https://github.com/WireMock-Net/WireMock.Net/issues/289) - Bug: When WatchStaticMappings=true throws exceptions on updating the mapping files [bug]
|
||||
- [#290](https://github.com/WireMock-Net/WireMock.Net/issues/290) - Request body is dropped if verb is REPORT [bug]
|
||||
- [#291](https://github.com/WireMock-Net/WireMock.Net/issues/291) - Define multiple scenarios for the same url path and switch to it at run-time? [question]
|
||||
- [#292](https://github.com/WireMock-Net/WireMock.Net/issues/292) - Can't start server in Xamarin Android [bug]
|
||||
|
||||
# 1.0.20.0 (17 June 2019)
|
||||
- [#284](https://github.com/WireMock-Net/WireMock.Net/pull/284) - Add SaveToFile in the mapping [feature] contributed by [StefH](https://github.com/StefH)
|
||||
|
||||
# 1.0.19.0 (15 June 2019)
|
||||
- [#279](https://github.com/WireMock-Net/WireMock.Net/issues/279) - How to simulate disconnect? [question]
|
||||
- [#283](https://github.com/WireMock-Net/WireMock.Net/issues/283) - Support equal-sign in query [bug]
|
||||
|
||||
# 1.0.18.0 (10 June 2019)
|
||||
- [#282](https://github.com/WireMock-Net/WireMock.Net/pull/282) - WireMock.Net.Standalone : Add --WireMockLogger commandline argument [feature] contributed by [StefH](https://github.com/StefH)
|
||||
|
||||
# 1.0.17.0 (05 June 2019)
|
||||
- [#278](https://github.com/WireMock-Net/WireMock.Net/pull/278) - Add support for HandleBars File (to read a file) [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#276](https://github.com/WireMock-Net/WireMock.Net/issues/276) - No server response in Postman and Receive Failure in Fiddler [invalid]
|
||||
|
||||
# 1.0.16.0 (16 May 2019)
|
||||
- [#274](https://github.com/WireMock-Net/WireMock.Net/pull/274) - Sign Assembly [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#160](https://github.com/WireMock-Net/WireMock.Net/issues/160) - Feature: Sign 'WireMock.Net' [feature]
|
||||
- [#267](https://github.com/WireMock-Net/WireMock.Net/issues/267) - Assembly does not have strong name
|
||||
|
||||
# 1.0.15.0 (04 May 2019)
|
||||
- [#271](https://github.com/WireMock-Net/WireMock.Net/pull/271) - Support Dynamic response files using Handlebars templating [bug, feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#272](https://github.com/WireMock-Net/WireMock.Net/pull/272) - Add unit test for JsonPath and BodyAsFile mapping contributed by [denstorti](https://github.com/denstorti)
|
||||
- [#273](https://github.com/WireMock-Net/WireMock.Net/pull/273) - Dynamic response handlebars templating (2) [bug, feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#270](https://github.com/WireMock-Net/WireMock.Net/issues/270) - Dynamic response files using Handlebars templating [bug, question]
|
||||
|
||||
# 1.0.14.0 (20 April 2019)
|
||||
- [#269](https://github.com/WireMock-Net/WireMock.Net/pull/269) - Add JmesPath matcher [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#268](https://github.com/WireMock-Net/WireMock.Net/issues/268) - Swagger UI for admin api [question]
|
||||
|
||||
# 1.0.13.0 (11 April 2019)
|
||||
- [#266](https://github.com/WireMock-Net/WireMock.Net/pull/266) - [265] Add file upload to allow mocking of file operations contributed by [JackCreativeCrew](https://github.com/JackCreativeCrew)
|
||||
- [#265](https://github.com/WireMock-Net/WireMock.Net/issues/265) - File Upload [feature]
|
||||
|
||||
# 1.0.12.0 (05 April 2019)
|
||||
- [#264](https://github.com/WireMock-Net/WireMock.Net/pull/264) - Proxy : also save multipart as string in mapping file contributed by [StefH](https://github.com/StefH)
|
||||
- [#263](https://github.com/WireMock-Net/WireMock.Net/issues/263) - Content-Type multipart/form-data is not serialized in proxy and recording mode [bug]
|
||||
|
||||
# 1.0.11.0 (30 March 2019)
|
||||
- [#261](https://github.com/WireMock-Net/WireMock.Net/pull/261) - Fix BodyAsJson transform bug in ResponseMessageTransformer contributed by [psypilat](https://github.com/psypilat)
|
||||
- [#262](https://github.com/WireMock-Net/WireMock.Net/pull/262) - Add ProvideResponse_WithJsonBodyAndTransform test contributed by [psypilat](https://github.com/psypilat)
|
||||
|
||||
# 1.0.10.0 (27 March 2019)
|
||||
- [#260](https://github.com/WireMock-Net/WireMock.Net/pull/260) - Fix Response.Delay property serialization [bug] contributed by [StefH](https://github.com/StefH)
|
||||
- [#257](https://github.com/WireMock-Net/WireMock.Net/issues/257) - Doc: Update outdated [question]
|
||||
- [#258](https://github.com/WireMock-Net/WireMock.Net/issues/258) - InvalidProgramException when following running as standalone process example with dotnetcore [invalid]
|
||||
|
||||
# 1.0.9.0 (25 March 2019)
|
||||
- [#256](https://github.com/WireMock-Net/WireMock.Net/pull/256) - Fixed Multi Param Match logic contributed by [StefH](https://github.com/StefH)
|
||||
- [#255](https://github.com/WireMock-Net/WireMock.Net/issues/255) - ExactMatcher with array pattern not working? [bug]
|
||||
|
||||
# 1.0.8.0 (12 March 2019)
|
||||
- [#254](https://github.com/WireMock-Net/WireMock.Net/pull/254) - RequestMessageParamMatcher supports Ignore Case for the key [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#251](https://github.com/WireMock-Net/WireMock.Net/issues/251) - Problem with Request Match WithBody [question]
|
||||
- [#253](https://github.com/WireMock-Net/WireMock.Net/issues/253) - Request Path and query parameter keys are case-sensitive
|
||||
|
||||
# 1.0.7.0 (19 January 2019)
|
||||
- [#244](https://github.com/WireMock-Net/WireMock.Net/pull/244) - Fix BodyAsFile to also allow relative paths [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#240](https://github.com/WireMock-Net/WireMock.Net/issues/240) - How to submit mappings for multiple request, responses [feature]
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<VersionPrefix>1.0.7</VersionPrefix>
|
||||
<VersionPrefix>1.0.25</VersionPrefix>
|
||||
</PropertyGroup>
|
||||
|
||||
<Choose>
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
https://github.com/StefH/GitHubReleaseNotes
|
||||
|
||||
GitHubReleaseNotes.exe --output CHANGELOG.md --skip-empty-releases --version 1.0.7.0
|
||||
GitHubReleaseNotes.exe --output CHANGELOG.md --skip-empty-releases --version 1.0.25.0
|
||||
@@ -3,12 +3,14 @@ A C# .NET version based on [mock4net](https://github.com/alexvictoor/mock4net) w
|
||||
|
||||
## Key Features
|
||||
* HTTP response stubbing, matchable on URL/Path, headers, cookies and body content patterns
|
||||
* Runs in unit tests, as a standalone process, as windows service, as Azure or IIS or as docker
|
||||
* Library can be used in unit tests and integration tests
|
||||
* Runs as a standalone process, as windows service, as Azure/IIS or as docker
|
||||
* Configurable via a fluent DotNet API, JSON files and JSON over HTTP
|
||||
* Record/playback of stubs (proxying)
|
||||
* Per-request conditional proxying
|
||||
* Stateful behaviour simulation
|
||||
* Response transformation
|
||||
* Response templating / transformation using Handlebars and extensions
|
||||
* Can be used locally or in CI/CD scenarios.
|
||||
|
||||
## Info
|
||||
| | |
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=XUA/@EntryIndexedValue">XUA</s:String>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=funcs/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Heyenrath/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Jmes/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=randomizer/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Stef/@EntryIndexedValue">True</s:Boolean>
|
||||
</wpf:ResourceDictionary>
|
||||
@@ -24,7 +24,7 @@ steps:
|
||||
# - https://github.com/Microsoft/vsts-tasks/issues/8291
|
||||
#
|
||||
- script: |
|
||||
%USERPROFILE%\.dotnet\tools\dotnet-sonarscanner begin /k:"wiremock" /d:sonar.organization="stefh-github" /d:sonar.host.url="https://sonarcloud.io" /d:sonar.login="$(SONAR_TOKEN)" /v:"$(buildId)" /d:sonar.cs.opencover.reportsPaths="**\coverage.opencover.xml"
|
||||
%USERPROFILE%\.dotnet\tools\dotnet-sonarscanner begin /k:"wiremock" /o:"stefh-github" /d:sonar.host.url="https://sonarcloud.io" /d:sonar.login="$(SONAR_TOKEN)" /v:"$(buildId)" /d:sonar.cs.opencover.reportsPaths="**\coverage.opencover.xml"
|
||||
displayName: Begin SonarScanner
|
||||
|
||||
# Build source, tests and run tests for net452 and netcoreapp2.1 (with coverage)
|
||||
@@ -38,6 +38,9 @@ steps:
|
||||
%USERPROFILE%\.dotnet\tools\dotnet-sonarscanner end /d:sonar.login="$(SONAR_TOKEN)"
|
||||
displayName: End SonarScanner
|
||||
|
||||
- task: whitesource.ws-bolt.bolt.wss.WhiteSource Bolt@19
|
||||
displayName: 'WhiteSource Bolt'
|
||||
|
||||
# Upload coverage to codecov.io
|
||||
- script: |
|
||||
%USERPROFILE%\.nuget\packages\codecov\1.1.0\tools\codecov.exe -f "./test/WireMock.Net.Tests/coverage.opencover.xml" -t $(CODECOV_TOKEN)
|
||||
|
||||
@@ -52,6 +52,12 @@ namespace WireMock.Net.Client
|
||||
var scenarioStates = api.GetScenariosAsync().Result;
|
||||
Console.WriteLine($"GetScenariosAsync = {JsonConvert.SerializeObject(scenarioStates)}");
|
||||
|
||||
var postFileResult = api.PostFileAsync("1.cs", "C# Hello").GetAwaiter().GetResult();
|
||||
Console.WriteLine($"postFileResult = {JsonConvert.SerializeObject(postFileResult)}");
|
||||
|
||||
var getFileResult = api.GetFileAsync("1.cs").GetAwaiter().GetResult();
|
||||
Console.WriteLine($"getFileResult = {getFileResult}");
|
||||
|
||||
Console.WriteLine("Press any key to quit");
|
||||
Console.ReadKey();
|
||||
}
|
||||
|
||||
@@ -49,5 +49,45 @@ namespace WireMock.Net.ConsoleApplication
|
||||
{
|
||||
return File.ReadAllBytes(Path.GetFileName(path) == path ? Path.Combine(GetMappingFolder(), path) : path);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IFileSystemHandler.ReadResponseBodyAsFile"/>
|
||||
public string ReadResponseBodyAsString(string path)
|
||||
{
|
||||
return File.ReadAllText(Path.GetFileName(path) == path ? Path.Combine(GetMappingFolder(), path) : path);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IFileSystemHandler.FileExists"/>
|
||||
public bool FileExists(string path)
|
||||
{
|
||||
return File.Exists(AdjustPath(path));
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IFileSystemHandler.WriteFile(string, byte[])"/>
|
||||
public void WriteFile(string path, byte[] bytes)
|
||||
{
|
||||
File.WriteAllBytes(AdjustPath(path), bytes);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IFileSystemHandler.DeleteFile"/>
|
||||
public void DeleteFile(string path)
|
||||
{
|
||||
File.Delete(AdjustPath(path));
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IFileSystemHandler.ReadFile"/>
|
||||
public byte[] ReadFile(string path)
|
||||
{
|
||||
return File.ReadAllBytes(AdjustPath(path));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adjusts the path to the MappingFolder.
|
||||
/// </summary>
|
||||
/// <param name="path">The path.</param>
|
||||
/// <returns>Adjusted path</returns>
|
||||
private string AdjustPath(string path)
|
||||
{
|
||||
return Path.Combine(GetMappingFolder(), path);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -33,7 +33,8 @@ namespace WireMock.Net.ConsoleApplication
|
||||
PostWireMockMiddlewareInit = app => { System.Console.WriteLine($"PostWireMockMiddlewareInit : {app.GetType()}"); },
|
||||
Logger = new WireMockConsoleLogger(),
|
||||
|
||||
FileSystemHandler = new CustomFileSystemFileHandler()
|
||||
// Uncomment below if you want to use the CustomFileSystemFileHandler
|
||||
// FileSystemHandler = new CustomFileSystemFileHandler()
|
||||
});
|
||||
System.Console.WriteLine("FluentMockServer listening at {0}", string.Join(",", server.Urls));
|
||||
|
||||
@@ -93,6 +94,13 @@ namespace WireMock.Net.ConsoleApplication
|
||||
)
|
||||
.RespondWith(Response.Create().WithBody("XPathMatcher!"));
|
||||
|
||||
server
|
||||
.Given(Request.Create()
|
||||
.WithPath("/xpaths").UsingPost()
|
||||
.WithBody(new[] { new XPathMatcher("/todo-list[count(todo-item) = 3]"), new XPathMatcher("/todo-list[count(todo-item) = 4]") })
|
||||
)
|
||||
.RespondWith(Response.Create().WithBody("xpaths!"));
|
||||
|
||||
server
|
||||
.Given(Request
|
||||
.Create()
|
||||
@@ -438,6 +446,17 @@ namespace WireMock.Net.ConsoleApplication
|
||||
.WithBody("<xml>ok</xml>")
|
||||
);
|
||||
|
||||
server.Given(Request.Create()
|
||||
.WithPath("/services/query/")
|
||||
.WithParam("q", "SELECT Id from User where username='user@gmail.com'")
|
||||
.UsingGet())
|
||||
.RespondWith(Response.Create()
|
||||
.WithStatusCode(200)
|
||||
.WithHeader("Content-Type", "application/json")
|
||||
.WithBodyAsJson(new { Id = "5bdf076c-5654-4b3e-842c-7caf1fabf8c9" }));
|
||||
|
||||
System.Console.WriteLine(JsonConvert.SerializeObject(server.MappingModels, Formatting.Indented));
|
||||
|
||||
System.Console.WriteLine("Press any key to stop the server");
|
||||
System.Console.ReadKey();
|
||||
server.Stop();
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using Newtonsoft.Json;
|
||||
using WireMock.Server;
|
||||
using WireMock.Settings;
|
||||
|
||||
@@ -8,14 +10,15 @@ namespace WireMock.Net.Console.Proxy.Net452
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
string[] urls = { "http://localhost:9091/", "https://localhost:9443/" };
|
||||
var server = FluentMockServer.Start(new FluentMockServerSettings
|
||||
{
|
||||
Urls = new[] { "http://localhost:9091/", "https://localhost:9443/" },
|
||||
Urls = urls,
|
||||
StartAdminInterface = true,
|
||||
ReadStaticMappings = false,
|
||||
ProxyAndRecordSettings = new ProxyAndRecordSettings
|
||||
{
|
||||
Url = "https://www.google.com",
|
||||
Url = "http://postman-echo.com/post",
|
||||
//ClientX509Certificate2ThumbprintOrSubjectName = "www.yourclientcertname.com OR yourcertificatethumbprint (only if the service you're proxying to requires it)",
|
||||
SaveMapping = true,
|
||||
SaveMappingToFile = false,
|
||||
@@ -28,6 +31,13 @@ namespace WireMock.Net.Console.Proxy.Net452
|
||||
System.Console.WriteLine(JsonConvert.SerializeObject(eventRecordArgs.NewItems, Formatting.Indented));
|
||||
};
|
||||
|
||||
var uri = new Uri(urls[0]);
|
||||
var form = new MultipartFormDataContent
|
||||
{
|
||||
{ new StringContent("data"), "test", "test.txt" }
|
||||
};
|
||||
new HttpClient().PostAsync(uri, form).GetAwaiter().GetResult();
|
||||
|
||||
System.Console.WriteLine("Press any key to stop the server");
|
||||
System.Console.ReadKey();
|
||||
server.Stop();
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"profiles": {
|
||||
"WireMock.Net.StandAlone.NETCoreApp": {
|
||||
"commandName": "Project",
|
||||
"commandLineArgs": "--Urls http://*:9091"
|
||||
"commandLineArgs": "--Urls http://*:9091 --WireMockLogger WireMockConsoleLogger"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -44,7 +44,7 @@
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Linq.Dynamic.Core" publicKeyToken="0f07ec44de6ac832" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-1.0.9.0" newVersion="1.0.9.0" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-1.0.12.0" newVersion="1.0.12.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||
|
||||
@@ -225,8 +225,8 @@
|
||||
<Reference Include="System.IO.Pipelines, Version=4.0.0.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\System.IO.Pipelines.4.5.2\lib\netstandard2.0\System.IO.Pipelines.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Linq.Dynamic.Core, Version=1.0.9.0, Culture=neutral, PublicKeyToken=0f07ec44de6ac832, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\System.Linq.Dynamic.Core.1.0.9\lib\net46\System.Linq.Dynamic.Core.dll</HintPath>
|
||||
<Reference Include="System.Linq.Dynamic.Core, Version=1.0.12.0, Culture=neutral, PublicKeyToken=0f07ec44de6ac832, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\System.Linq.Dynamic.Core.1.0.12\lib\net46\System.Linq.Dynamic.Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Memory, Version=4.0.1.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\System.Memory.4.5.1\lib\netstandard2.0\System.Memory.dll</HintPath>
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
<package id="System.Collections.Immutable" version="1.5.0" targetFramework="net461" />
|
||||
<package id="System.Diagnostics.DiagnosticSource" version="4.5.0" targetFramework="net461" />
|
||||
<package id="System.IO.Pipelines" version="4.5.2" targetFramework="net461" />
|
||||
<package id="System.Linq.Dynamic.Core" version="1.0.9" targetFramework="net461" />
|
||||
<package id="System.Linq.Dynamic.Core" version="1.0.12" targetFramework="net461" />
|
||||
<package id="System.Memory" version="4.5.1" targetFramework="net461" />
|
||||
<package id="System.Numerics.Vectors" version="4.5.0" targetFramework="net461" />
|
||||
<package id="System.Reflection.Metadata" version="1.6.0" targetFramework="net461" />
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
[assembly: InternalsVisibleTo("WireMock.Net.Tests")]
|
||||
[assembly: InternalsVisibleTo("WireMock.Net.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e138ec44d93acac565953052636eb8d5e7e9f27ddb030590055cd1a0ab2069a5623f1f77ca907d78e0b37066ca0f6d63da7eecc3fcb65b76aa8ebeccf7ebe1d11264b8404cd9b1cbbf2c83f566e033b3e54129f6ef28daffff776ba7aebbc53c0d635ebad8f45f78eb3f7e0459023c218f003416e080f96a1a3c5ffeb56bee9e")]
|
||||
|
||||
// Needed for Moq in the UnitTest project
|
||||
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
|
||||
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")]
|
||||
@@ -50,7 +50,7 @@ namespace WireMock.Net.StandAlone
|
||||
AdminUsername = parser.GetStringValue("AdminUsername"),
|
||||
AdminPassword = parser.GetStringValue("AdminPassword"),
|
||||
MaxRequestLogCount = parser.GetIntValue("MaxRequestLogCount"),
|
||||
RequestLogExpirationDuration = parser.GetIntValue("RequestLogExpirationDuration"),
|
||||
RequestLogExpirationDuration = parser.GetIntValue("RequestLogExpirationDuration")
|
||||
};
|
||||
|
||||
if (logger != null)
|
||||
@@ -58,6 +58,11 @@ namespace WireMock.Net.StandAlone
|
||||
settings.Logger = logger;
|
||||
}
|
||||
|
||||
if (parser.GetStringValue("WireMockLogger") == "WireMockConsoleLogger")
|
||||
{
|
||||
settings.Logger = new WireMockConsoleLogger();
|
||||
}
|
||||
|
||||
if (parser.Contains("Port"))
|
||||
{
|
||||
settings.Port = parser.GetIntValue("Port");
|
||||
@@ -82,9 +87,7 @@ namespace WireMock.Net.StandAlone
|
||||
|
||||
settings.Logger.Debug("WireMock.Net server arguments [{0}]", string.Join(", ", args.Select(a => $"'{a}'")));
|
||||
|
||||
FluentMockServer server = Start(settings);
|
||||
|
||||
return server;
|
||||
return Start(settings);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,10 @@
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
|
||||
<CodeAnalysisRuleSet>WireMock.Net.StandAlone.ruleset</CodeAnalysisRuleSet>
|
||||
<SignAssembly>true</SignAssembly>
|
||||
<AssemblyOriginatorKeyFile>../WireMock.Net/WireMock.Net.snk</AssemblyOriginatorKeyFile>
|
||||
<!--<DelaySign>true</DelaySign>-->
|
||||
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
|
||||
|
||||
@@ -9,5 +9,10 @@
|
||||
/// Gets or sets the matcher.
|
||||
/// </summary>
|
||||
public MatcherModel Matcher { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the matchers.
|
||||
/// </summary>
|
||||
public MatcherModel[] Matchers { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -39,13 +39,18 @@ namespace WireMock.Admin.Mappings
|
||||
public string SetStateTo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The request.
|
||||
/// The request model.
|
||||
/// </summary>
|
||||
public RequestModel Request { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The response.
|
||||
/// The response model.
|
||||
/// </summary>
|
||||
public ResponseModel Response { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Saves this mapping as a static mapping file.
|
||||
/// </summary>
|
||||
public bool? SaveToFile { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,11 @@
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Defines if the key should be matched using case-ignore.
|
||||
/// </summary>
|
||||
public bool? IgnoreCase { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the matchers.
|
||||
/// </summary>
|
||||
|
||||
@@ -58,9 +58,9 @@ namespace WireMock.Admin.Mappings
|
||||
public EncodingModel BodyEncoding { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether [use transformer].
|
||||
/// Use Handlebars transformer.
|
||||
/// </summary>
|
||||
public bool UseTransformer { get; set; }
|
||||
public bool? UseTransformer { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the headers.
|
||||
|
||||
@@ -167,5 +167,42 @@ namespace WireMock.Client
|
||||
/// </summary>
|
||||
[Post("__admin/scenarios")]
|
||||
Task<StatusModel> ResetScenariosAsync();
|
||||
|
||||
/// <summary>
|
||||
/// Create a new File
|
||||
/// </summary>
|
||||
/// <param name="filename">The filename</param>
|
||||
/// <param name="body">The body</param>
|
||||
[Post("__admin/files/{filename}")]
|
||||
Task<StatusModel> PostFileAsync([Path] string filename, [Body] string body);
|
||||
|
||||
/// <summary>
|
||||
/// Update an existing File
|
||||
/// </summary>
|
||||
/// <param name="filename">The filename</param>
|
||||
/// <param name="body">The body</param>
|
||||
[Put("__admin/files/{filename}")]
|
||||
Task<StatusModel> PutFileAsync([Path] string filename, [Body] string body);
|
||||
|
||||
/// <summary>
|
||||
/// Get the content of an existing File
|
||||
/// </summary>
|
||||
/// <param name="filename">The filename</param>
|
||||
[Get("__admin/files/{filename}")]
|
||||
Task<string> GetFileAsync([Path] string filename);
|
||||
|
||||
/// <summary>
|
||||
/// Delete an existing File
|
||||
/// </summary>
|
||||
/// <param name="filename">The filename</param>
|
||||
[Delete("__admin/files/{filename}")]
|
||||
Task<StatusModel> DeleteFileAsync([Path] string filename);
|
||||
|
||||
/// <summary>
|
||||
/// Check if a file exists
|
||||
/// </summary>
|
||||
/// <param name="filename">The filename</param>
|
||||
[Head("__admin/files/{filename}")]
|
||||
Task FileExistsAsync([Path] string filename);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using JetBrains.Annotations;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace WireMock.Handlers
|
||||
{
|
||||
@@ -18,40 +19,74 @@ namespace WireMock.Handlers
|
||||
/// </summary>
|
||||
/// <param name="path">The path.</param>
|
||||
/// <returns>true if path refers to an existing directory; false if the directory does not exist or an error occurs when trying to determine if the specified directory exists.</returns>
|
||||
bool FolderExists(string path);
|
||||
bool FolderExists([NotNull] string path);
|
||||
|
||||
/// <summary>
|
||||
/// Creates all directories and subdirectories in the specified path unless they already exist.
|
||||
/// </summary>
|
||||
/// <param name="path">The path.</param>
|
||||
void CreateFolder(string path);
|
||||
void CreateFolder([NotNull] string path);
|
||||
|
||||
/// <summary>
|
||||
/// Returns an enumerable collection of file names in a specified path.
|
||||
/// </summary>
|
||||
/// <param name="path">The path.</param>
|
||||
/// <returns>An enumerable collection of the full names (including paths) for the files in the directory specified by path.</returns>
|
||||
IEnumerable<string> EnumerateFiles(string path);
|
||||
IEnumerable<string> EnumerateFiles([NotNull] string path);
|
||||
|
||||
/// <summary>
|
||||
/// Read a static mapping file as text.
|
||||
/// </summary>
|
||||
/// <param name="path">The path (folder + filename with .json extension).</param>
|
||||
/// <returns>The file content as text.</returns>
|
||||
string ReadMappingFile(string path);
|
||||
string ReadMappingFile([NotNull] string path);
|
||||
|
||||
/// <summary>
|
||||
/// Write the static mapping.
|
||||
/// Write the static mapping file.
|
||||
/// </summary>
|
||||
/// <param name="path">The path (folder + filename with .json extension).</param>
|
||||
/// <param name="text">The text.</param>
|
||||
void WriteMappingFile(string path, string text);
|
||||
void WriteMappingFile([NotNull] string path, [NotNull] string text);
|
||||
|
||||
/// <summary>
|
||||
/// Read a response body file as byte[].
|
||||
/// </summary>
|
||||
/// <param name="path">The path or filename from the file to read.</param>
|
||||
/// <returns>The file content as bytes.</returns>
|
||||
byte[] ReadResponseBodyAsFile([NotNull] string path);
|
||||
|
||||
/// <summary>
|
||||
/// Read a response body file as text.
|
||||
/// </summary>
|
||||
/// <param name="path">The path or filename from the file to read.</param>
|
||||
/// <returns>The file content as text.</returns>
|
||||
string ReadResponseBodyAsString([NotNull] string path);
|
||||
|
||||
/// <summary>
|
||||
/// Delete a file.
|
||||
/// </summary>
|
||||
/// <param name="filename">The filename.</param>
|
||||
void DeleteFile([NotNull] string filename);
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the given path refers to an existing file on disk.
|
||||
/// </summary>
|
||||
/// <param name="filename">The filename.</param>
|
||||
/// <returns>true if path refers to an existing file; false if the file does not exist.</returns>
|
||||
bool FileExists([NotNull] string filename);
|
||||
|
||||
/// <summary>
|
||||
/// Write a file.
|
||||
/// </summary>
|
||||
/// <param name="filename">The filename.</param>
|
||||
/// <param name="bytes">The bytes.</param>
|
||||
void WriteFile([NotNull] string filename, [NotNull] byte[] bytes);
|
||||
|
||||
/// <summary>
|
||||
/// Read a file as bytes.
|
||||
/// </summary>
|
||||
/// <param name="filename">The filename.</param>
|
||||
/// <returns>The file content as bytes.</returns>
|
||||
byte[] ReadResponseBodyAsFile(string path);
|
||||
byte[] ReadFile([NotNull] string filename);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
using JetBrains.Annotations;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using WireMock.Validation;
|
||||
|
||||
@@ -12,8 +11,26 @@ namespace WireMock.Handlers
|
||||
{
|
||||
private static readonly string AdminMappingsFolder = Path.Combine("__admin", "mappings");
|
||||
|
||||
private readonly string _rootFolder;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="LocalFileSystemHandler"/> class.
|
||||
/// </summary>
|
||||
public LocalFileSystemHandler() : this(Directory.GetCurrentDirectory())
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="LocalFileSystemHandler"/> class.
|
||||
/// </summary>
|
||||
/// <param name="rootFolder">The root folder.</param>
|
||||
public LocalFileSystemHandler(string rootFolder)
|
||||
{
|
||||
_rootFolder = rootFolder;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IFileSystemHandler.FolderExists"/>
|
||||
public bool FolderExists([NotNull] string path)
|
||||
public bool FolderExists(string path)
|
||||
{
|
||||
Check.NotNullOrEmpty(path, nameof(path));
|
||||
|
||||
@@ -21,7 +38,7 @@ namespace WireMock.Handlers
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IFileSystemHandler.CreateFolder"/>
|
||||
public void CreateFolder([NotNull] string path)
|
||||
public void CreateFolder(string path)
|
||||
{
|
||||
Check.NotNullOrEmpty(path, nameof(path));
|
||||
|
||||
@@ -29,7 +46,7 @@ namespace WireMock.Handlers
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IFileSystemHandler.EnumerateFiles"/>
|
||||
public IEnumerable<string> EnumerateFiles([NotNull] string path)
|
||||
public IEnumerable<string> EnumerateFiles(string path)
|
||||
{
|
||||
Check.NotNullOrEmpty(path, nameof(path));
|
||||
|
||||
@@ -39,19 +56,19 @@ namespace WireMock.Handlers
|
||||
/// <inheritdoc cref="IFileSystemHandler.GetMappingFolder"/>
|
||||
public string GetMappingFolder()
|
||||
{
|
||||
return Path.Combine(Directory.GetCurrentDirectory(), AdminMappingsFolder);
|
||||
return Path.Combine(_rootFolder, AdminMappingsFolder);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IFileSystemHandler.ReadMappingFile"/>
|
||||
public string ReadMappingFile([NotNull] string path)
|
||||
public string ReadMappingFile(string path)
|
||||
{
|
||||
Check.NotNullOrEmpty(path, nameof(path));
|
||||
|
||||
return File.ReadAllText(path);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IFileSystemHandler.WriteMappingFile"/>
|
||||
public void WriteMappingFile([NotNull] string path, [NotNull] string text)
|
||||
/// <inheritdoc cref="IFileSystemHandler.WriteMappingFile(string, string)"/>
|
||||
public void WriteMappingFile(string path, string text)
|
||||
{
|
||||
Check.NotNullOrEmpty(path, nameof(path));
|
||||
Check.NotNull(text, nameof(text));
|
||||
@@ -68,5 +85,58 @@ namespace WireMock.Handlers
|
||||
// Else the path will just be as-is.
|
||||
return File.ReadAllBytes(Path.GetFileName(path) == path ? Path.Combine(GetMappingFolder(), path) : path);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IFileSystemHandler.ReadResponseBodyAsString"/>
|
||||
public string ReadResponseBodyAsString(string path)
|
||||
{
|
||||
Check.NotNullOrEmpty(path, nameof(path));
|
||||
|
||||
// In case the path is a filename, the path will be adjusted to the MappingFolder.
|
||||
// Else the path will just be as-is.
|
||||
return File.ReadAllText(Path.GetFileName(path) == path ? Path.Combine(GetMappingFolder(), path) : path);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IFileSystemHandler.FileExists"/>
|
||||
public bool FileExists(string filename)
|
||||
{
|
||||
Check.NotNullOrEmpty(filename, nameof(filename));
|
||||
|
||||
return File.Exists(AdjustPath(filename));
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IFileSystemHandler.WriteFile(string, byte[])"/>
|
||||
public void WriteFile(string filename, byte[] bytes)
|
||||
{
|
||||
Check.NotNullOrEmpty(filename, nameof(filename));
|
||||
Check.NotNull(bytes, nameof(bytes));
|
||||
|
||||
File.WriteAllBytes(AdjustPath(filename), bytes);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IFileSystemHandler.DeleteFile"/>
|
||||
public void DeleteFile(string filename)
|
||||
{
|
||||
Check.NotNullOrEmpty(filename, nameof(filename));
|
||||
|
||||
File.Delete(AdjustPath(filename));
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IFileSystemHandler.ReadFile"/>
|
||||
public byte[] ReadFile(string filename)
|
||||
{
|
||||
Check.NotNullOrEmpty(filename, nameof(filename));
|
||||
|
||||
return File.ReadAllBytes(AdjustPath(filename));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adjusts the path to the MappingFolder.
|
||||
/// </summary>
|
||||
/// <param name="filename">The path.</param>
|
||||
/// <returns>Adjusted path</returns>
|
||||
private string AdjustPath(string filename)
|
||||
{
|
||||
return Path.Combine(GetMappingFolder(), filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
using System;
|
||||
using JetBrains.Annotations;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using JetBrains.Annotations;
|
||||
using WireMock.Matchers.Request;
|
||||
using WireMock.ResponseProviders;
|
||||
using WireMock.Settings;
|
||||
|
||||
namespace WireMock
|
||||
{
|
||||
@@ -60,6 +61,11 @@ namespace WireMock
|
||||
/// </summary>
|
||||
IResponseProvider Provider { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The FluentMockServerSettings.
|
||||
/// </summary>
|
||||
IFluentMockServerSettings Settings { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Is State started ?
|
||||
/// </summary>
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
using System;
|
||||
using JetBrains.Annotations;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using JetBrains.Annotations;
|
||||
using WireMock.Matchers.Request;
|
||||
using WireMock.ResponseProviders;
|
||||
using WireMock.Settings;
|
||||
|
||||
namespace WireMock
|
||||
{
|
||||
@@ -38,6 +39,9 @@ namespace WireMock
|
||||
/// <inheritdoc cref="IMapping.Provider" />
|
||||
public IResponseProvider Provider { get; }
|
||||
|
||||
/// <inheritdoc cref="IMapping.Settings" />
|
||||
public IFluentMockServerSettings Settings { get; }
|
||||
|
||||
/// <inheritdoc cref="IMapping.IsStartState" />
|
||||
public bool IsStartState => Scenario == null || Scenario != null && NextState != null && ExecutionConditionState == null;
|
||||
|
||||
@@ -50,17 +54,21 @@ namespace WireMock
|
||||
/// <param name="guid">The unique identifier.</param>
|
||||
/// <param name="title">The unique title (can be null).</param>
|
||||
/// <param name="path">The full file path from this mapping title (can be null).</param>
|
||||
/// <param name="settings">The FluentMockServerSettings.</param>
|
||||
/// <param name="requestMatcher">The request matcher.</param>
|
||||
/// <param name="provider">The provider.</param>
|
||||
/// <param name="priority">The priority for this mapping.</param>
|
||||
/// <param name="scenario">The scenario. [Optional]</param>
|
||||
/// <param name="executionConditionState">State in which the current mapping can occur. [Optional]</param>
|
||||
/// <param name="nextState">The next state which will occur after the current mapping execution. [Optional]</param>
|
||||
public Mapping(Guid guid, [CanBeNull] string title, [CanBeNull] string path, IRequestMatcher requestMatcher, IResponseProvider provider, int priority, [CanBeNull] string scenario, [CanBeNull] string executionConditionState, [CanBeNull] string nextState)
|
||||
public Mapping(Guid guid, [CanBeNull] string title, [CanBeNull] string path,
|
||||
[NotNull] IFluentMockServerSettings settings, [NotNull] IRequestMatcher requestMatcher, [NotNull] IResponseProvider provider,
|
||||
int priority, [CanBeNull] string scenario, [CanBeNull] string executionConditionState, [CanBeNull] string nextState)
|
||||
{
|
||||
Guid = guid;
|
||||
Title = title;
|
||||
Path = path;
|
||||
Settings = settings;
|
||||
RequestMatcher = requestMatcher;
|
||||
Provider = provider;
|
||||
Priority = priority;
|
||||
@@ -72,7 +80,7 @@ namespace WireMock
|
||||
/// <inheritdoc cref="IMapping.ResponseToAsync" />
|
||||
public async Task<ResponseMessage> ResponseToAsync(RequestMessage requestMessage)
|
||||
{
|
||||
return await Provider.ProvideResponseAsync(requestMessage);
|
||||
return await Provider.ProvideResponseAsync(requestMessage, Settings);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IMapping.GetRequestMatchResult" />
|
||||
|
||||
@@ -4,5 +4,6 @@
|
||||
/// The registration callback.
|
||||
/// </summary>
|
||||
/// <param name="mapping">The mapping.</param>
|
||||
public delegate void RegistrationCallback(IMapping mapping);
|
||||
/// <param name="saveToFile">Optional boolean to indicate if this mapping should be saved as static mapping file.</param>
|
||||
public delegate void RegistrationCallback(IMapping mapping, bool saveToFile = false);
|
||||
}
|
||||
@@ -39,7 +39,12 @@ namespace WireMock.Matchers
|
||||
/// <inheritdoc cref="IStringMatcher.IsMatch"/>
|
||||
public double IsMatch(string input)
|
||||
{
|
||||
return MatchBehaviourHelper.Convert(MatchBehaviour, MatchScores.ToScore(_values.Select(value => value.Equals(input))));
|
||||
if (_values.Length == 1)
|
||||
{
|
||||
return MatchBehaviourHelper.Convert(MatchBehaviour, MatchScores.ToScore(_values[0] == input));
|
||||
}
|
||||
|
||||
return MatchBehaviourHelper.Convert(MatchBehaviour, MatchScores.ToScore(_values.Contains(input)));
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IStringMatcher.GetPatterns"/>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using System.Linq;
|
||||
using JetBrains.Annotations;
|
||||
using JetBrains.Annotations;
|
||||
using System.Linq;
|
||||
using WireMock.Validation;
|
||||
|
||||
namespace WireMock.Matchers
|
||||
@@ -10,8 +10,15 @@ namespace WireMock.Matchers
|
||||
/// <seealso cref="IObjectMatcher" />
|
||||
public class ExactObjectMatcher : IObjectMatcher
|
||||
{
|
||||
private readonly object _object;
|
||||
private readonly byte[] _bytes;
|
||||
/// <summary>
|
||||
/// Gets the value as object.
|
||||
/// </summary>
|
||||
public object ValueAsObject { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value as byte[].
|
||||
/// </summary>
|
||||
public byte[] ValueAsBytes { get; }
|
||||
|
||||
/// <inheritdoc cref="IMatcher.MatchBehaviour"/>
|
||||
public MatchBehaviour MatchBehaviour { get; }
|
||||
@@ -33,7 +40,7 @@ namespace WireMock.Matchers
|
||||
{
|
||||
Check.NotNull(value, nameof(value));
|
||||
|
||||
_object = value;
|
||||
ValueAsObject = value;
|
||||
MatchBehaviour = matchBehaviour;
|
||||
}
|
||||
|
||||
@@ -54,14 +61,14 @@ namespace WireMock.Matchers
|
||||
{
|
||||
Check.NotNull(value, nameof(value));
|
||||
|
||||
_bytes = value;
|
||||
ValueAsBytes = value;
|
||||
MatchBehaviour = matchBehaviour;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IObjectMatcher.IsMatch"/>
|
||||
public double IsMatch(object input)
|
||||
{
|
||||
bool equals = _object != null ? Equals(_object, input) : _bytes.SequenceEqual((byte[])input);
|
||||
bool equals = ValueAsObject != null ? Equals(ValueAsObject, input) : ValueAsBytes.SequenceEqual((byte[])input);
|
||||
return MatchBehaviourHelper.Convert(MatchBehaviour, MatchScores.ToScore(equals));
|
||||
}
|
||||
|
||||
|
||||
83
src/WireMock.Net/Matchers/JmesPathMatcher.cs
Normal file
83
src/WireMock.Net/Matchers/JmesPathMatcher.cs
Normal file
@@ -0,0 +1,83 @@
|
||||
using DevLab.JmesPath;
|
||||
using JetBrains.Annotations;
|
||||
using Newtonsoft.Json;
|
||||
using System.Linq;
|
||||
using WireMock.Validation;
|
||||
|
||||
namespace WireMock.Matchers
|
||||
{
|
||||
/// <summary>
|
||||
/// http://jmespath.org/
|
||||
/// </summary>
|
||||
public class JmesPathMatcher : IStringMatcher, IObjectMatcher
|
||||
{
|
||||
private readonly string[] _patterns;
|
||||
|
||||
/// <inheritdoc cref="IMatcher.MatchBehaviour"/>
|
||||
public MatchBehaviour MatchBehaviour { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="JmesPathMatcher"/> class.
|
||||
/// </summary>
|
||||
/// <param name="patterns">The patterns.</param>
|
||||
public JmesPathMatcher([NotNull] params string[] patterns) : this(MatchBehaviour.AcceptOnMatch, patterns)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="JmesPathMatcher"/> class.
|
||||
/// </summary>
|
||||
/// <param name="matchBehaviour">The match behaviour.</param>
|
||||
/// <param name="patterns">The patterns.</param>
|
||||
public JmesPathMatcher(MatchBehaviour matchBehaviour, [NotNull] params string[] patterns)
|
||||
{
|
||||
Check.NotNull(patterns, nameof(patterns));
|
||||
|
||||
MatchBehaviour = matchBehaviour;
|
||||
_patterns = patterns;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IStringMatcher.IsMatch"/>
|
||||
public double IsMatch(string input)
|
||||
{
|
||||
double match = MatchScores.Mismatch;
|
||||
if (input != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
match = MatchScores.ToScore(_patterns.Select(pattern => bool.Parse(new JmesPath().Transform(input, pattern))));
|
||||
}
|
||||
catch (JsonException)
|
||||
{
|
||||
// just ignore JsonException
|
||||
}
|
||||
}
|
||||
|
||||
return MatchBehaviourHelper.Convert(MatchBehaviour, match);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IObjectMatcher.IsMatch"/>
|
||||
public double IsMatch(object input)
|
||||
{
|
||||
double match = MatchScores.Mismatch;
|
||||
|
||||
// When input is null or byte[], return Mismatch.
|
||||
if (input != null && !(input is byte[]))
|
||||
{
|
||||
string inputAsString = JsonConvert.SerializeObject(input);
|
||||
return IsMatch(inputAsString);
|
||||
}
|
||||
|
||||
return MatchBehaviourHelper.Convert(MatchBehaviour, match);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IStringMatcher.GetPatterns"/>
|
||||
public string[] GetPatterns()
|
||||
{
|
||||
return _patterns;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IMatcher.Name"/>
|
||||
public string Name => "JmesPathMatcher";
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
|
||||
namespace WireMock.Matchers
|
||||
@@ -54,6 +55,7 @@ namespace WireMock.Matchers
|
||||
/// </summary>
|
||||
/// <param name="values">The values.</param>
|
||||
/// <returns>average score</returns>
|
||||
[SuppressMessage("ReSharper", "PossibleMultipleEnumeration")]
|
||||
public static double ToScore(IEnumerable<bool> values)
|
||||
{
|
||||
return values.Any() ? values.Select(ToScore).Average() : Mismatch;
|
||||
@@ -64,6 +66,7 @@ namespace WireMock.Matchers
|
||||
/// </summary>
|
||||
/// <param name="values">The values.</param>
|
||||
/// <returns>average score</returns>
|
||||
[SuppressMessage("ReSharper", "PossibleMultipleEnumeration")]
|
||||
public static double ToScore(IEnumerable<double> values)
|
||||
{
|
||||
return values.Any() ? values.Average() : Mismatch;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using JetBrains.Annotations;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using WireMock.Util;
|
||||
using WireMock.Validation;
|
||||
|
||||
@@ -26,16 +27,16 @@ namespace WireMock.Matchers.Request
|
||||
public Func<object, bool> JsonFunc { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The matcher.
|
||||
/// The matchers.
|
||||
/// </summary>
|
||||
public IMatcher Matcher { get; }
|
||||
public IMatcher[] Matchers { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RequestMessageBodyMatcher"/> class.
|
||||
/// </summary>
|
||||
/// <param name="matchBehaviour">The match behaviour.</param>
|
||||
/// <param name="body">The body.</param>
|
||||
public RequestMessageBodyMatcher(MatchBehaviour matchBehaviour, [NotNull] string body) : this(new WildcardMatcher(matchBehaviour, body))
|
||||
public RequestMessageBodyMatcher(MatchBehaviour matchBehaviour, [NotNull] string body) : this(new[] { new WildcardMatcher(matchBehaviour, body) }.Cast<IMatcher>().ToArray())
|
||||
{
|
||||
}
|
||||
|
||||
@@ -44,7 +45,7 @@ namespace WireMock.Matchers.Request
|
||||
/// </summary>
|
||||
/// <param name="matchBehaviour">The match behaviour.</param>
|
||||
/// <param name="body">The body.</param>
|
||||
public RequestMessageBodyMatcher(MatchBehaviour matchBehaviour, [NotNull] byte[] body) : this(new ExactObjectMatcher(matchBehaviour, body))
|
||||
public RequestMessageBodyMatcher(MatchBehaviour matchBehaviour, [NotNull] byte[] body) : this(new[] { new ExactObjectMatcher(matchBehaviour, body) }.Cast<IMatcher>().ToArray())
|
||||
{
|
||||
}
|
||||
|
||||
@@ -53,7 +54,7 @@ namespace WireMock.Matchers.Request
|
||||
/// </summary>
|
||||
/// <param name="matchBehaviour">The match behaviour.</param>
|
||||
/// <param name="body">The body.</param>
|
||||
public RequestMessageBodyMatcher(MatchBehaviour matchBehaviour, [NotNull] object body) : this(new ExactObjectMatcher(matchBehaviour, body))
|
||||
public RequestMessageBodyMatcher(MatchBehaviour matchBehaviour, [NotNull] object body) : this(new[] { new ExactObjectMatcher(matchBehaviour, body) }.Cast<IMatcher>().ToArray())
|
||||
{
|
||||
}
|
||||
|
||||
@@ -90,25 +91,24 @@ namespace WireMock.Matchers.Request
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RequestMessageBodyMatcher"/> class.
|
||||
/// </summary>
|
||||
/// <param name="matcher">The matcher.</param>
|
||||
public RequestMessageBodyMatcher([NotNull] IMatcher matcher)
|
||||
/// <param name="matchers">The matchers.</param>
|
||||
public RequestMessageBodyMatcher([NotNull] params IMatcher[] matchers)
|
||||
{
|
||||
Check.NotNull(matcher, nameof(matcher));
|
||||
|
||||
Matcher = matcher;
|
||||
Check.NotNull(matchers, nameof(matchers));
|
||||
Matchers = matchers;
|
||||
}
|
||||
|
||||
/// <see cref="IRequestMatcher.GetMatchingScore"/>
|
||||
public double GetMatchingScore(RequestMessage requestMessage, RequestMatchResult requestMatchResult)
|
||||
{
|
||||
double score = IsMatch(requestMessage);
|
||||
double score = CalculateMatchScore(requestMessage);
|
||||
return requestMatchResult.AddScore(GetType(), score);
|
||||
}
|
||||
|
||||
private double IsMatch(RequestMessage requestMessage)
|
||||
private double CalculateMatchScore(RequestMessage requestMessage, IMatcher matcher)
|
||||
{
|
||||
// Check if the matcher is a IObjectMatcher
|
||||
if (Matcher is IObjectMatcher objectMatcher)
|
||||
if (matcher is IObjectMatcher objectMatcher)
|
||||
{
|
||||
// If the body is a JSON object, try to match.
|
||||
if (requestMessage?.BodyData?.DetectedBodyType == BodyType.Json)
|
||||
@@ -124,7 +124,7 @@ namespace WireMock.Matchers.Request
|
||||
}
|
||||
|
||||
// Check if the matcher is a IStringMatcher
|
||||
if (Matcher is IStringMatcher stringMatcher)
|
||||
if (matcher is IStringMatcher stringMatcher)
|
||||
{
|
||||
// If the body is a Json or a String, use the BodyAsString to match on.
|
||||
if (requestMessage?.BodyData?.DetectedBodyType == BodyType.Json || requestMessage?.BodyData?.DetectedBodyType == BodyType.String)
|
||||
@@ -133,6 +133,16 @@ namespace WireMock.Matchers.Request
|
||||
}
|
||||
}
|
||||
|
||||
return MatchScores.Mismatch;
|
||||
}
|
||||
|
||||
private double CalculateMatchScore(RequestMessage requestMessage)
|
||||
{
|
||||
if (Matchers != null && Matchers.Any())
|
||||
{
|
||||
return Matchers.Max(matcher => CalculateMatchScore(requestMessage, matcher));
|
||||
}
|
||||
|
||||
if (Func != null)
|
||||
{
|
||||
return MatchScores.ToScore(requestMessage?.BodyData?.DetectedBodyType == BodyType.String && Func(requestMessage.BodyData.BodyAsString));
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using System;
|
||||
using JetBrains.Annotations;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using JetBrains.Annotations;
|
||||
using WireMock.Util;
|
||||
using WireMock.Validation;
|
||||
|
||||
@@ -24,6 +24,11 @@ namespace WireMock.Matchers.Request
|
||||
/// </summary>
|
||||
public string Key { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Defines if the key should be matched using case-ignore.
|
||||
/// </summary>
|
||||
public bool? IgnoreCase { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The matchers.
|
||||
/// </summary>
|
||||
@@ -34,7 +39,8 @@ namespace WireMock.Matchers.Request
|
||||
/// </summary>
|
||||
/// <param name="matchBehaviour">The match behaviour.</param>
|
||||
/// <param name="key">The key.</param>
|
||||
public RequestMessageParamMatcher(MatchBehaviour matchBehaviour, [NotNull] string key) : this(matchBehaviour, key, (IStringMatcher[])null)
|
||||
/// <param name="ignoreCase">Defines if the key should be matched using case-ignore.</param>
|
||||
public RequestMessageParamMatcher(MatchBehaviour matchBehaviour, [NotNull] string key, bool ignoreCase) : this(matchBehaviour, key, ignoreCase, (IStringMatcher[])null)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -43,8 +49,9 @@ namespace WireMock.Matchers.Request
|
||||
/// </summary>
|
||||
/// <param name="matchBehaviour">The match behaviour.</param>
|
||||
/// <param name="key">The key.</param>
|
||||
/// <param name="ignoreCase">Defines if the key should be matched using case-ignore.</param>
|
||||
/// <param name="values">The values.</param>
|
||||
public RequestMessageParamMatcher(MatchBehaviour matchBehaviour, [NotNull] string key, [CanBeNull] string[] values) : this(matchBehaviour, key, values?.Select(value => new ExactMatcher(matchBehaviour, value)).Cast<IStringMatcher>().ToArray())
|
||||
public RequestMessageParamMatcher(MatchBehaviour matchBehaviour, [NotNull] string key, bool ignoreCase, [CanBeNull] string[] values) : this(matchBehaviour, key, ignoreCase, values?.Select(value => new ExactMatcher(matchBehaviour, value)).Cast<IStringMatcher>().ToArray())
|
||||
{
|
||||
}
|
||||
|
||||
@@ -53,13 +60,15 @@ namespace WireMock.Matchers.Request
|
||||
/// </summary>
|
||||
/// <param name="matchBehaviour">The match behaviour.</param>
|
||||
/// <param name="key">The key.</param>
|
||||
/// <param name="ignoreCase">Defines if the key should be matched using case-ignore.</param>
|
||||
/// <param name="matchers">The matchers.</param>
|
||||
public RequestMessageParamMatcher(MatchBehaviour matchBehaviour, [NotNull] string key, [CanBeNull] IStringMatcher[] matchers)
|
||||
public RequestMessageParamMatcher(MatchBehaviour matchBehaviour, [NotNull] string key, bool ignoreCase, [CanBeNull] IStringMatcher[] matchers)
|
||||
{
|
||||
Check.NotNull(key, nameof(key));
|
||||
|
||||
_matchBehaviour = matchBehaviour;
|
||||
Key = key;
|
||||
IgnoreCase = ignoreCase;
|
||||
Matchers = matchers;
|
||||
}
|
||||
|
||||
@@ -88,7 +97,7 @@ namespace WireMock.Matchers.Request
|
||||
return MatchScores.ToScore(requestMessage.Query != null && Funcs.Any(f => f(requestMessage.Query)));
|
||||
}
|
||||
|
||||
WireMockList<string> valuesPresentInRequestMessage = requestMessage.GetParameter(Key);
|
||||
WireMockList<string> valuesPresentInRequestMessage = requestMessage.GetParameter(Key, IgnoreCase ?? false);
|
||||
if (valuesPresentInRequestMessage == null)
|
||||
{
|
||||
// Key is not present at all, just return Mismatch
|
||||
@@ -97,15 +106,8 @@ namespace WireMock.Matchers.Request
|
||||
|
||||
if (Matchers != null && Matchers.Any())
|
||||
{
|
||||
// Matchers are defined, just use the matchers to calculate the match score.
|
||||
var scores = new List<double>();
|
||||
foreach (string valuePresentInRequestMessage in valuesPresentInRequestMessage)
|
||||
{
|
||||
double score = Matchers.Max(m => m.IsMatch(valuePresentInRequestMessage));
|
||||
scores.Add(score);
|
||||
}
|
||||
|
||||
return scores.Any() ? scores.Average() : MatchScores.Mismatch;
|
||||
// Return the score based on Matchers and valuesPresentInRequestMessage
|
||||
return CalculateScore(valuesPresentInRequestMessage);
|
||||
}
|
||||
|
||||
if (Matchers == null || !Matchers.Any())
|
||||
@@ -116,5 +118,35 @@ namespace WireMock.Matchers.Request
|
||||
|
||||
return MatchScores.Mismatch;
|
||||
}
|
||||
|
||||
private double CalculateScore(WireMockList<string> valuesPresentInRequestMessage)
|
||||
{
|
||||
var total = new List<double>();
|
||||
|
||||
// If the total patterns in all matchers > values in message, use the matcher as base
|
||||
if (Matchers.Sum(m => m.GetPatterns().Length) > valuesPresentInRequestMessage.Count)
|
||||
{
|
||||
foreach (var matcher in Matchers)
|
||||
{
|
||||
double score = 0d;
|
||||
foreach (string valuePresentInRequestMessage in valuesPresentInRequestMessage)
|
||||
{
|
||||
score += matcher.IsMatch(valuePresentInRequestMessage) / matcher.GetPatterns().Length;
|
||||
}
|
||||
|
||||
total.Add(score);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (string valuePresentInRequestMessage in valuesPresentInRequestMessage)
|
||||
{
|
||||
double score = Matchers.Max(m => m.IsMatch(valuePresentInRequestMessage));
|
||||
total.Add(score);
|
||||
}
|
||||
}
|
||||
|
||||
return total.Any() ? MatchScores.ToScore(total) : MatchScores.Mismatch;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -56,7 +56,18 @@ namespace WireMock.Owin
|
||||
|
||||
public Task StartAsync()
|
||||
{
|
||||
_host = new WebHostBuilder()
|
||||
var builder = new WebHostBuilder();
|
||||
|
||||
// Workaround for https://github.com/WireMock-Net/WireMock.Net/issues/292
|
||||
// On some platforms, AppContext.BaseDirectory is null, which causes WebHostBuilder to fail if ContentRoot is not
|
||||
// specified (even though we don't actually use that base path mechanism, since we have our own way of configuring
|
||||
// a filesystem handler).
|
||||
if (string.IsNullOrEmpty(AppContext.BaseDirectory))
|
||||
{
|
||||
builder.UseContentRoot(System.IO.Directory.GetCurrentDirectory());
|
||||
}
|
||||
|
||||
_host = builder
|
||||
.ConfigureServices(services =>
|
||||
{
|
||||
services.AddSingleton(_options.FileSystemHandler);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
[assembly: InternalsVisibleTo("WireMock.Net.StandAlone")]
|
||||
[assembly: InternalsVisibleTo("WireMock.Net.Tests")]
|
||||
[assembly: InternalsVisibleTo("WireMock.Net.StandAlone, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e138ec44d93acac565953052636eb8d5e7e9f27ddb030590055cd1a0ab2069a5623f1f77ca907d78e0b37066ca0f6d63da7eecc3fcb65b76aa8ebeccf7ebe1d11264b8404cd9b1cbbf2c83f566e033b3e54129f6ef28daffff776ba7aebbc53c0d635ebad8f45f78eb3f7e0459023c218f003416e080f96a1a3c5ffeb56bee9e")]
|
||||
[assembly: InternalsVisibleTo("WireMock.Net.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e138ec44d93acac565953052636eb8d5e7e9f27ddb030590055cd1a0ab2069a5623f1f77ca907d78e0b37066ca0f6d63da7eecc3fcb65b76aa8ebeccf7ebe1d11264b8404cd9b1cbbf2c83f566e033b3e54129f6ef28daffff776ba7aebbc53c0d635ebad8f45f78eb3f7e0459023c218f003416e080f96a1a3c5ffeb56bee9e")]
|
||||
|
||||
// Needed for Moq in the UnitTest project
|
||||
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
|
||||
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")]
|
||||
@@ -1,5 +1,5 @@
|
||||
using System;
|
||||
using JetBrains.Annotations;
|
||||
using JetBrains.Annotations;
|
||||
using System;
|
||||
using WireMock.Matchers;
|
||||
|
||||
namespace WireMock.RequestBuilders
|
||||
@@ -16,6 +16,13 @@ namespace WireMock.RequestBuilders
|
||||
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
|
||||
IRequestBuilder WithBody([NotNull] IMatcher matcher);
|
||||
|
||||
/// <summary>
|
||||
/// WithBody: IMatcher[]
|
||||
/// </summary>
|
||||
/// <param name="matchers">The matchers.</param>
|
||||
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
|
||||
IRequestBuilder WithBody([NotNull] IMatcher[] matchers);
|
||||
|
||||
/// <summary>
|
||||
/// WithBody: Body as string
|
||||
/// </summary>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using System;
|
||||
using JetBrains.Annotations;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using JetBrains.Annotations;
|
||||
using WireMock.Matchers;
|
||||
using WireMock.Util;
|
||||
|
||||
@@ -19,6 +19,15 @@ namespace WireMock.RequestBuilders
|
||||
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
|
||||
IRequestBuilder WithParam([NotNull] string key, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch);
|
||||
|
||||
/// <summary>
|
||||
/// WithParam: matching on key only.
|
||||
/// </summary>
|
||||
/// <param name="key">The key.</param>
|
||||
/// <param name="ignoreCase">Defines if the key should be matched using case-ignore.</param>
|
||||
/// <param name="matchBehaviour">The match behaviour (optional).</param>
|
||||
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
|
||||
IRequestBuilder WithParam([NotNull] string key, bool ignoreCase, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch);
|
||||
|
||||
/// <summary>
|
||||
/// WithParam: matching on key and values.
|
||||
/// </summary>
|
||||
@@ -27,6 +36,15 @@ namespace WireMock.RequestBuilders
|
||||
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
|
||||
IRequestBuilder WithParam([NotNull] string key, [CanBeNull] params string[] values);
|
||||
|
||||
/// <summary>
|
||||
/// WithParam: matching on key and values.
|
||||
/// </summary>
|
||||
/// <param name="key">The key.</param>
|
||||
/// <param name="ignoreCase">Defines if the key should be matched using case-ignore.</param>
|
||||
/// <param name="values">The values.</param>
|
||||
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
|
||||
IRequestBuilder WithParam([NotNull] string key, bool ignoreCase, [CanBeNull] params string[] values);
|
||||
|
||||
/// <summary>
|
||||
/// WithParam: matching on key and matchers.
|
||||
/// </summary>
|
||||
@@ -35,6 +53,15 @@ namespace WireMock.RequestBuilders
|
||||
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
|
||||
IRequestBuilder WithParam([NotNull] string key, [CanBeNull] params IStringMatcher[] matchers);
|
||||
|
||||
/// <summary>
|
||||
/// WithParam: matching on key and matchers.
|
||||
/// </summary>
|
||||
/// <param name="key">The key.</param>
|
||||
/// <param name="ignoreCase">Defines if the key should be matched using case-ignore.</param>
|
||||
/// <param name="matchers">The matchers.</param>
|
||||
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
|
||||
IRequestBuilder WithParam([NotNull] string key, bool ignoreCase, [CanBeNull] params IStringMatcher[] matchers);
|
||||
|
||||
/// <summary>
|
||||
/// WithParam: matching on key, values and matchBehaviour.
|
||||
/// </summary>
|
||||
@@ -44,6 +71,16 @@ namespace WireMock.RequestBuilders
|
||||
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
|
||||
IRequestBuilder WithParam([NotNull] string key, MatchBehaviour matchBehaviour, [CanBeNull] params string[] values);
|
||||
|
||||
/// <summary>
|
||||
/// WithParam: matching on key, values and matchBehaviour.
|
||||
/// </summary>
|
||||
/// <param name="key">The key.</param>
|
||||
/// <param name="ignoreCase">Defines if the key should be matched using case-ignore.</param>
|
||||
/// <param name="values">The values.</param>
|
||||
/// <param name="matchBehaviour">The match behaviour.</param>
|
||||
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
|
||||
IRequestBuilder WithParam([NotNull] string key, MatchBehaviour matchBehaviour, bool ignoreCase = false, [CanBeNull] params string[] values);
|
||||
|
||||
/// <summary>
|
||||
/// WithParam: matching on key, matchers and matchBehaviour.
|
||||
/// </summary>
|
||||
@@ -53,6 +90,16 @@ namespace WireMock.RequestBuilders
|
||||
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
|
||||
IRequestBuilder WithParam([NotNull] string key, MatchBehaviour matchBehaviour, [CanBeNull] params IStringMatcher[] matchers);
|
||||
|
||||
/// <summary>
|
||||
/// WithParam: matching on key, matchers and matchBehaviour.
|
||||
/// </summary>
|
||||
/// <param name="key">The key.</param>
|
||||
/// <param name="ignoreCase">Defines if the key should be matched using case-ignore.</param>
|
||||
/// <param name="matchers">The matchers.</param>
|
||||
/// <param name="matchBehaviour">The match behaviour.</param>
|
||||
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
|
||||
IRequestBuilder WithParam([NotNull] string key, MatchBehaviour matchBehaviour, bool ignoreCase = false, [CanBeNull] params IStringMatcher[] matchers);
|
||||
|
||||
/// <summary>
|
||||
/// WithParam: matching on functions.
|
||||
/// </summary>
|
||||
|
||||
73
src/WireMock.Net/RequestBuilders/Request.WithBody.cs
Normal file
73
src/WireMock.Net/RequestBuilders/Request.WithBody.cs
Normal file
@@ -0,0 +1,73 @@
|
||||
using System;
|
||||
using WireMock.Matchers;
|
||||
using WireMock.Matchers.Request;
|
||||
using WireMock.Validation;
|
||||
|
||||
namespace WireMock.RequestBuilders
|
||||
{
|
||||
public partial class Request
|
||||
{
|
||||
/// <inheritdoc cref="IBodyRequestBuilder.WithBody(string, MatchBehaviour)"/>
|
||||
public IRequestBuilder WithBody(string body, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
|
||||
{
|
||||
_requestMatchers.Add(new RequestMessageBodyMatcher(matchBehaviour, body));
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IBodyRequestBuilder.WithBody(byte[], MatchBehaviour)"/>
|
||||
public IRequestBuilder WithBody(byte[] body, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
|
||||
{
|
||||
_requestMatchers.Add(new RequestMessageBodyMatcher(matchBehaviour, body));
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IBodyRequestBuilder.WithBody(object, MatchBehaviour)"/>
|
||||
public IRequestBuilder WithBody(object body, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
|
||||
{
|
||||
_requestMatchers.Add(new RequestMessageBodyMatcher(matchBehaviour, body));
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IBodyRequestBuilder.WithBody(IMatcher[])"/>
|
||||
public IRequestBuilder WithBody(IMatcher matcher)
|
||||
{
|
||||
return WithBody(new[] { matcher });
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IBodyRequestBuilder.WithBody(IMatcher[])"/>
|
||||
public IRequestBuilder WithBody(IMatcher[] matchers)
|
||||
{
|
||||
Check.NotNull(matchers, nameof(matchers));
|
||||
|
||||
_requestMatchers.Add(new RequestMessageBodyMatcher(matchers));
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IBodyRequestBuilder.WithBody(Func{string, bool})"/>
|
||||
public IRequestBuilder WithBody(Func<string, bool> func)
|
||||
{
|
||||
Check.NotNull(func, nameof(func));
|
||||
|
||||
_requestMatchers.Add(new RequestMessageBodyMatcher(func));
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IBodyRequestBuilder.WithBody(Func{byte[], bool})"/>
|
||||
public IRequestBuilder WithBody(Func<byte[], bool> func)
|
||||
{
|
||||
Check.NotNull(func, nameof(func));
|
||||
|
||||
_requestMatchers.Add(new RequestMessageBodyMatcher(func));
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IBodyRequestBuilder.WithBody(Func{object, bool})"/>
|
||||
public IRequestBuilder WithBody(Func<object, bool> func)
|
||||
{
|
||||
Check.NotNull(func, nameof(func));
|
||||
|
||||
_requestMatchers.Add(new RequestMessageBodyMatcher(func));
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
90
src/WireMock.Net/RequestBuilders/Request.WithParam.cs
Normal file
90
src/WireMock.Net/RequestBuilders/Request.WithParam.cs
Normal file
@@ -0,0 +1,90 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using WireMock.Matchers;
|
||||
using WireMock.Matchers.Request;
|
||||
using WireMock.Util;
|
||||
using WireMock.Validation;
|
||||
|
||||
namespace WireMock.RequestBuilders
|
||||
{
|
||||
public partial class Request
|
||||
{
|
||||
/// <inheritdoc cref="IParamsRequestBuilder.WithParam(string, MatchBehaviour)"/>
|
||||
public IRequestBuilder WithParam(string key, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
|
||||
{
|
||||
return WithParam(key, false, matchBehaviour);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IParamsRequestBuilder.WithParam(string, bool, MatchBehaviour)"/>
|
||||
public IRequestBuilder WithParam(string key, bool ignoreCase, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
|
||||
{
|
||||
Check.NotNull(key, nameof(key));
|
||||
|
||||
_requestMatchers.Add(new RequestMessageParamMatcher(matchBehaviour, key, ignoreCase));
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IParamsRequestBuilder.WithParam(string, string[])"/>
|
||||
public IRequestBuilder WithParam(string key, params string[] values)
|
||||
{
|
||||
return WithParam(key, MatchBehaviour.AcceptOnMatch, false, values);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IParamsRequestBuilder.WithParam(string, bool, string[])"/>
|
||||
public IRequestBuilder WithParam(string key, bool ignoreCase, params string[] values)
|
||||
{
|
||||
return WithParam(key, MatchBehaviour.AcceptOnMatch, ignoreCase, values);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IParamsRequestBuilder.WithParam(string, IStringMatcher[])"/>
|
||||
public IRequestBuilder WithParam(string key, params IStringMatcher[] matchers)
|
||||
{
|
||||
return WithParam(key, MatchBehaviour.AcceptOnMatch, false, matchers);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IParamsRequestBuilder.WithParam(string, bool, IStringMatcher[])"/>
|
||||
public IRequestBuilder WithParam(string key, bool ignoreCase, params IStringMatcher[] matchers)
|
||||
{
|
||||
return WithParam(key, MatchBehaviour.AcceptOnMatch, ignoreCase, matchers);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IParamsRequestBuilder.WithParam(string, MatchBehaviour, string[])"/>
|
||||
public IRequestBuilder WithParam(string key, MatchBehaviour matchBehaviour, params string[] values)
|
||||
{
|
||||
return WithParam(key, matchBehaviour, false, values);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IParamsRequestBuilder.WithParam(string, MatchBehaviour, bool, string[])"/>
|
||||
public IRequestBuilder WithParam(string key, MatchBehaviour matchBehaviour, bool ignoreCase = false, params string[] values)
|
||||
{
|
||||
Check.NotNull(key, nameof(key));
|
||||
|
||||
_requestMatchers.Add(new RequestMessageParamMatcher(matchBehaviour, key, ignoreCase, values));
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IParamsRequestBuilder.WithParam(string, MatchBehaviour, IStringMatcher[])"/>
|
||||
public IRequestBuilder WithParam(string key, MatchBehaviour matchBehaviour, params IStringMatcher[] matchers)
|
||||
{
|
||||
return WithParam(key, matchBehaviour, false, matchers);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IParamsRequestBuilder.WithParam(string, MatchBehaviour, bool, IStringMatcher[])"/>
|
||||
public IRequestBuilder WithParam(string key, MatchBehaviour matchBehaviour, bool ignoreCase, params IStringMatcher[] matchers)
|
||||
{
|
||||
Check.NotNull(key, nameof(key));
|
||||
|
||||
_requestMatchers.Add(new RequestMessageParamMatcher(matchBehaviour, key, ignoreCase, matchers));
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IParamsRequestBuilder.WithParam(Func{IDictionary{string, WireMockList{string}}, bool}[])"/>
|
||||
public IRequestBuilder WithParam(params Func<IDictionary<string, WireMockList<string>>, bool>[] funcs)
|
||||
{
|
||||
Check.NotNullOrEmpty(funcs, nameof(funcs));
|
||||
|
||||
_requestMatchers.Add(new RequestMessageParamMatcher(funcs));
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,6 @@ using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using WireMock.Matchers;
|
||||
using WireMock.Matchers.Request;
|
||||
using WireMock.Util;
|
||||
using WireMock.Validation;
|
||||
|
||||
namespace WireMock.RequestBuilders
|
||||
@@ -12,7 +11,7 @@ namespace WireMock.RequestBuilders
|
||||
/// <summary>
|
||||
/// The requests.
|
||||
/// </summary>
|
||||
public class Request : RequestMessageCompositeMatcher, IRequestBuilder
|
||||
public partial class Request : RequestMessageCompositeMatcher, IRequestBuilder
|
||||
{
|
||||
private readonly IList<IRequestMatcher> _requestMatchers;
|
||||
|
||||
@@ -234,111 +233,6 @@ namespace WireMock.RequestBuilders
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IBodyRequestBuilder.WithBody(string, MatchBehaviour)"/>
|
||||
public IRequestBuilder WithBody(string body, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
|
||||
{
|
||||
_requestMatchers.Add(new RequestMessageBodyMatcher(matchBehaviour, body));
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IBodyRequestBuilder.WithBody(byte[], MatchBehaviour)"/>
|
||||
public IRequestBuilder WithBody(byte[] body, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
|
||||
{
|
||||
_requestMatchers.Add(new RequestMessageBodyMatcher(matchBehaviour, body));
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IBodyRequestBuilder.WithBody(object, MatchBehaviour)"/>
|
||||
public IRequestBuilder WithBody(object body, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
|
||||
{
|
||||
_requestMatchers.Add(new RequestMessageBodyMatcher(matchBehaviour, body));
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IBodyRequestBuilder.WithBody(IMatcher)"/>
|
||||
public IRequestBuilder WithBody(IMatcher matcher)
|
||||
{
|
||||
Check.NotNull(matcher, nameof(matcher));
|
||||
|
||||
_requestMatchers.Add(new RequestMessageBodyMatcher(matcher));
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IBodyRequestBuilder.WithBody(Func{string, bool})"/>
|
||||
public IRequestBuilder WithBody(Func<string, bool> func)
|
||||
{
|
||||
Check.NotNull(func, nameof(func));
|
||||
|
||||
_requestMatchers.Add(new RequestMessageBodyMatcher(func));
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IBodyRequestBuilder.WithBody(Func{byte[], bool})"/>
|
||||
public IRequestBuilder WithBody(Func<byte[], bool> func)
|
||||
{
|
||||
Check.NotNull(func, nameof(func));
|
||||
|
||||
_requestMatchers.Add(new RequestMessageBodyMatcher(func));
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IBodyRequestBuilder.WithBody(Func{object, bool})"/>
|
||||
public IRequestBuilder WithBody(Func<object, bool> func)
|
||||
{
|
||||
Check.NotNull(func, nameof(func));
|
||||
|
||||
_requestMatchers.Add(new RequestMessageBodyMatcher(func));
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IParamsRequestBuilder.WithParam(string, MatchBehaviour)"/>
|
||||
public IRequestBuilder WithParam(string key, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
|
||||
{
|
||||
Check.NotNull(key, nameof(key));
|
||||
|
||||
_requestMatchers.Add(new RequestMessageParamMatcher(matchBehaviour, key));
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IParamsRequestBuilder.WithParam(string, string[])"/>
|
||||
public IRequestBuilder WithParam(string key, params string[] values)
|
||||
{
|
||||
return WithParam(key, MatchBehaviour.AcceptOnMatch, values);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IParamsRequestBuilder.WithParam(string, IStringMatcher[])"/>
|
||||
public IRequestBuilder WithParam(string key, params IStringMatcher[] matchers)
|
||||
{
|
||||
return WithParam(key, MatchBehaviour.AcceptOnMatch, matchers);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IParamsRequestBuilder.WithParam(string, MatchBehaviour, string[])"/>
|
||||
public IRequestBuilder WithParam(string key, MatchBehaviour matchBehaviour, params string[] values)
|
||||
{
|
||||
Check.NotNull(key, nameof(key));
|
||||
|
||||
_requestMatchers.Add(new RequestMessageParamMatcher(matchBehaviour, key, values));
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IParamsRequestBuilder.WithParam(string, MatchBehaviour, IStringMatcher[])"/>
|
||||
public IRequestBuilder WithParam(string key, MatchBehaviour matchBehaviour, params IStringMatcher[] matchers)
|
||||
{
|
||||
Check.NotNull(key, nameof(key));
|
||||
|
||||
_requestMatchers.Add(new RequestMessageParamMatcher(matchBehaviour, key, matchers));
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IParamsRequestBuilder.WithParam(Func{IDictionary{string, WireMockList{string}}, bool}[])"/>
|
||||
public IRequestBuilder WithParam(params Func<IDictionary<string, WireMockList<string>>, bool>[] funcs)
|
||||
{
|
||||
Check.NotNullOrEmpty(funcs, nameof(funcs));
|
||||
|
||||
_requestMatchers.Add(new RequestMessageParamMatcher(funcs));
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IHeadersAndCookiesRequestBuilder.WithHeader(string, string, MatchBehaviour)"/>
|
||||
public IRequestBuilder WithHeader(string name, string pattern, MatchBehaviour matchBehaviour)
|
||||
{
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
using System;
|
||||
using JetBrains.Annotations;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using JetBrains.Annotations;
|
||||
using WireMock.Models;
|
||||
using WireMock.Util;
|
||||
using WireMock.Validation;
|
||||
@@ -171,55 +171,25 @@ namespace WireMock
|
||||
Headers = headers?.ToDictionary(header => header.Key, header => new WireMockList<string>(header.Value));
|
||||
Cookies = cookies;
|
||||
RawQuery = WebUtility.UrlDecode(urlDetails.Url.Query);
|
||||
Query = ParseQuery(RawQuery);
|
||||
}
|
||||
|
||||
private static IDictionary<string, WireMockList<string>> ParseQuery(string queryString)
|
||||
{
|
||||
if (string.IsNullOrEmpty(queryString))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (queryString.StartsWith("?"))
|
||||
{
|
||||
queryString = queryString.Substring(1);
|
||||
}
|
||||
|
||||
return queryString.Split(new[] { '&' }, StringSplitOptions.RemoveEmptyEntries)
|
||||
.Aggregate(new Dictionary<string, WireMockList<string>>(),
|
||||
(dict, term) =>
|
||||
{
|
||||
string[] parts = term.Split(new[] { '=' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
string key = parts[0];
|
||||
if (!dict.ContainsKey(key))
|
||||
{
|
||||
dict.Add(key, new WireMockList<string>());
|
||||
}
|
||||
|
||||
if (parts.Length == 2)
|
||||
{
|
||||
string[] values = parts[1].Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries);
|
||||
dict[key].AddRange(values);
|
||||
}
|
||||
|
||||
return dict;
|
||||
});
|
||||
Query = QueryStringParser.Parse(RawQuery);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a query parameter.
|
||||
/// </summary>
|
||||
/// <param name="key">The key.</param>
|
||||
/// <param name="ignoreCase">Defines if the key should be matched using case-ignore.</param>
|
||||
/// <returns>The query parameter.</returns>
|
||||
public WireMockList<string> GetParameter(string key)
|
||||
public WireMockList<string> GetParameter(string key, bool ignoreCase = false)
|
||||
{
|
||||
if (Query == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return Query.ContainsKey(key) ? Query[key] : null;
|
||||
var query = !ignoreCase ? Query : new Dictionary<string, WireMockList<string>>(Query, StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
return query.ContainsKey(key) ? query[key] : null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,8 +7,8 @@ using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using WireMock.Handlers;
|
||||
using WireMock.Http;
|
||||
using WireMock.ResponseProviders;
|
||||
using WireMock.Settings;
|
||||
using WireMock.Transformers;
|
||||
using WireMock.Util;
|
||||
@@ -21,7 +21,6 @@ namespace WireMock.ResponseBuilders
|
||||
/// </summary>
|
||||
public class Response : IResponseBuilder
|
||||
{
|
||||
private readonly IFileSystemHandler _fileSystemHandler = new LocalFileSystemHandler();
|
||||
private HttpClient _httpClientForProxy;
|
||||
|
||||
/// <summary>
|
||||
@@ -221,18 +220,17 @@ namespace WireMock.ResponseBuilders
|
||||
|
||||
ResponseMessage.BodyData = new BodyData
|
||||
{
|
||||
BodyAsFileIsCached = cache
|
||||
BodyAsFileIsCached = cache,
|
||||
BodyAsFile = filename
|
||||
};
|
||||
|
||||
if (cache)
|
||||
if (cache && !UseTransformer)
|
||||
{
|
||||
ResponseMessage.BodyData.DetectedBodyType = BodyType.Bytes;
|
||||
ResponseMessage.BodyData.BodyAsBytes = _fileSystemHandler.ReadResponseBodyAsFile(filename);
|
||||
}
|
||||
else
|
||||
{
|
||||
ResponseMessage.BodyData.DetectedBodyType = BodyType.File;
|
||||
ResponseMessage.BodyData.BodyAsFile = filename;
|
||||
}
|
||||
|
||||
return this;
|
||||
@@ -373,12 +371,8 @@ namespace WireMock.ResponseBuilders
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The provide response.
|
||||
/// </summary>
|
||||
/// <param name="requestMessage">The request.</param>
|
||||
/// <returns>The <see cref="ResponseMessage"/>.</returns>
|
||||
public async Task<ResponseMessage> ProvideResponseAsync(RequestMessage requestMessage)
|
||||
/// <inheritdoc cref="IResponseProvider.ProvideResponseAsync(RequestMessage, IFluentMockServerSettings)"/>
|
||||
public async Task<ResponseMessage> ProvideResponseAsync(RequestMessage requestMessage, IFluentMockServerSettings settings)
|
||||
{
|
||||
Check.NotNull(requestMessage, nameof(requestMessage));
|
||||
|
||||
@@ -417,10 +411,16 @@ namespace WireMock.ResponseBuilders
|
||||
|
||||
if (UseTransformer)
|
||||
{
|
||||
return ResponseMessageTransformer.Transform(requestMessage, ResponseMessage);
|
||||
var factory = new HandlebarsContextFactory(settings.FileSystemHandler, settings.HandlebarsRegistrationCallback);
|
||||
var responseMessageTransformer = new ResponseMessageTransformer(factory);
|
||||
return responseMessageTransformer.Transform(requestMessage, ResponseMessage);
|
||||
}
|
||||
|
||||
if (!UseTransformer && ResponseMessage.BodyData?.BodyAsFileIsCached == true)
|
||||
{
|
||||
ResponseMessage.BodyData.BodyAsBytes = settings.FileSystemHandler.ReadResponseBodyAsFile(ResponseMessage.BodyData.BodyAsFile);
|
||||
}
|
||||
|
||||
// Just return normal defined ResponseMessage
|
||||
return ResponseMessage;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,10 @@ namespace WireMock
|
||||
internal static class ResponseMessageBuilder
|
||||
{
|
||||
private static string ContentTypeJson = "application/json";
|
||||
private static readonly IDictionary<string, WireMockList<string>> ContentTypeJsonHeaders = new Dictionary<string, WireMockList<string>> { { HttpKnownHeaderNames.ContentType, new WireMockList<string> { ContentTypeJson } } };
|
||||
private static readonly IDictionary<string, WireMockList<string>> ContentTypeJsonHeaders = new Dictionary<string, WireMockList<string>>
|
||||
{
|
||||
{ HttpKnownHeaderNames.ContentType, new WireMockList<string> { ContentTypeJson } }
|
||||
};
|
||||
|
||||
internal static ResponseMessage Create(string message, int statusCode = 200, Guid? guid = null)
|
||||
{
|
||||
@@ -24,11 +27,23 @@ namespace WireMock
|
||||
response.BodyData = new BodyData
|
||||
{
|
||||
DetectedBodyType = BodyType.Json,
|
||||
BodyAsJson = new StatusModel { Status = message, Guid = guid }
|
||||
BodyAsJson = new StatusModel
|
||||
{
|
||||
Guid = guid,
|
||||
Status = message
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
internal static ResponseMessage Create(int statusCode)
|
||||
{
|
||||
return new ResponseMessage
|
||||
{
|
||||
StatusCode = statusCode
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using JetBrains.Annotations;
|
||||
using WireMock.Validation;
|
||||
using WireMock.Settings;
|
||||
|
||||
namespace WireMock.ResponseProviders
|
||||
{
|
||||
@@ -9,14 +8,12 @@ namespace WireMock.ResponseProviders
|
||||
{
|
||||
private readonly Func<RequestMessage, Task<ResponseMessage>> _responseMessageFunc;
|
||||
|
||||
public DynamicAsyncResponseProvider([NotNull] Func<RequestMessage, Task<ResponseMessage>> responseMessageFunc)
|
||||
public DynamicAsyncResponseProvider(Func<RequestMessage, Task<ResponseMessage>> responseMessageFunc)
|
||||
{
|
||||
Check.NotNull(responseMessageFunc, nameof(responseMessageFunc));
|
||||
|
||||
_responseMessageFunc = responseMessageFunc;
|
||||
}
|
||||
|
||||
public Task<ResponseMessage> ProvideResponseAsync(RequestMessage requestMessage)
|
||||
public Task<ResponseMessage> ProvideResponseAsync(RequestMessage requestMessage, IFluentMockServerSettings settings)
|
||||
{
|
||||
return _responseMessageFunc(requestMessage);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using JetBrains.Annotations;
|
||||
using WireMock.Validation;
|
||||
using WireMock.Settings;
|
||||
|
||||
namespace WireMock.ResponseProviders
|
||||
{
|
||||
@@ -9,14 +8,12 @@ namespace WireMock.ResponseProviders
|
||||
{
|
||||
private readonly Func<RequestMessage, ResponseMessage> _responseMessageFunc;
|
||||
|
||||
public DynamicResponseProvider([NotNull] Func<RequestMessage, ResponseMessage> responseMessageFunc)
|
||||
public DynamicResponseProvider(Func<RequestMessage, ResponseMessage> responseMessageFunc)
|
||||
{
|
||||
Check.NotNull(responseMessageFunc, nameof(responseMessageFunc));
|
||||
|
||||
_responseMessageFunc = responseMessageFunc;
|
||||
}
|
||||
|
||||
public Task<ResponseMessage> ProvideResponseAsync(RequestMessage requestMessage)
|
||||
public Task<ResponseMessage> ProvideResponseAsync(RequestMessage requestMessage, IFluentMockServerSettings settings)
|
||||
{
|
||||
return Task.FromResult(_responseMessageFunc(requestMessage));
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Threading.Tasks;
|
||||
using JetBrains.Annotations;
|
||||
using JetBrains.Annotations;
|
||||
using System.Threading.Tasks;
|
||||
using WireMock.Settings;
|
||||
|
||||
namespace WireMock.ResponseProviders
|
||||
{
|
||||
@@ -12,7 +13,8 @@ namespace WireMock.ResponseProviders
|
||||
/// The provide response.
|
||||
/// </summary>
|
||||
/// <param name="requestMessage">The request.</param>
|
||||
/// <param name="settings">The FluentMockServerSettings.</param>
|
||||
/// <returns>The <see cref="ResponseMessage"/>.</returns>
|
||||
Task<ResponseMessage> ProvideResponseAsync([NotNull] RequestMessage requestMessage);
|
||||
Task<ResponseMessage> ProvideResponseAsync([NotNull] RequestMessage requestMessage, [NotNull] IFluentMockServerSettings settings);
|
||||
}
|
||||
}
|
||||
@@ -1,26 +1,21 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using JetBrains.Annotations;
|
||||
using WireMock.Settings;
|
||||
using WireMock.Validation;
|
||||
|
||||
namespace WireMock.ResponseProviders
|
||||
{
|
||||
internal class ProxyAsyncResponseProvider : IResponseProvider
|
||||
{
|
||||
private readonly Func<RequestMessage, IProxyAndRecordSettings, Task<ResponseMessage>> _responseMessageFunc;
|
||||
private readonly IProxyAndRecordSettings _settings;
|
||||
private readonly Func<RequestMessage, IFluentMockServerSettings, Task<ResponseMessage>> _responseMessageFunc;
|
||||
private readonly IFluentMockServerSettings _settings;
|
||||
|
||||
public ProxyAsyncResponseProvider([NotNull] Func<RequestMessage, IProxyAndRecordSettings, Task<ResponseMessage>> responseMessageFunc, [NotNull] IProxyAndRecordSettings settings)
|
||||
public ProxyAsyncResponseProvider(Func<RequestMessage, IFluentMockServerSettings, Task<ResponseMessage>> responseMessageFunc, IFluentMockServerSettings settings)
|
||||
{
|
||||
Check.NotNull(responseMessageFunc, nameof(responseMessageFunc));
|
||||
Check.NotNull(settings, nameof(settings));
|
||||
|
||||
_responseMessageFunc = responseMessageFunc;
|
||||
_settings = settings;
|
||||
}
|
||||
|
||||
public Task<ResponseMessage> ProvideResponseAsync(RequestMessage requestMessage)
|
||||
public Task<ResponseMessage> ProvideResponseAsync(RequestMessage requestMessage, IFluentMockServerSettings settings)
|
||||
{
|
||||
return _responseMessageFunc(requestMessage, _settings);
|
||||
}
|
||||
|
||||
@@ -21,14 +21,14 @@ namespace WireMock.Serialization
|
||||
var headerMatchers = request.GetRequestMessageMatchers<RequestMessageHeaderMatcher>();
|
||||
var cookieMatchers = request.GetRequestMessageMatchers<RequestMessageCookieMatcher>();
|
||||
var paramsMatchers = request.GetRequestMessageMatchers<RequestMessageParamMatcher>();
|
||||
var bodyMatcher = request.GetRequestMessageMatcher<RequestMessageBodyMatcher>();
|
||||
var methodMatcher = request.GetRequestMessageMatcher<RequestMessageMethodMatcher>();
|
||||
var bodyMatcher = request.GetRequestMessageMatcher<RequestMessageBodyMatcher>();
|
||||
|
||||
var mappingModel = new MappingModel
|
||||
{
|
||||
Guid = mapping.Guid,
|
||||
Title = mapping.Title,
|
||||
Priority = mapping.Priority,
|
||||
Priority = mapping.Priority != 0 ? mapping.Priority : (int?)null,
|
||||
Scenario = mapping.Scenario,
|
||||
WhenStateIs = mapping.ExecutionConditionState,
|
||||
SetStateTo = mapping.NextState,
|
||||
@@ -66,20 +66,30 @@ namespace WireMock.Serialization
|
||||
Params = paramsMatchers != null && paramsMatchers.Any() ? paramsMatchers.Select(pm => new ParamModel
|
||||
{
|
||||
Name = pm.Key,
|
||||
IgnoreCase = pm.IgnoreCase == true ? true : (bool?)null,
|
||||
Matchers = MatcherMapper.Map(pm.Matchers)
|
||||
}).ToList() : null,
|
||||
|
||||
Body = methodMatcher?.Methods != null && methodMatcher.Methods.Any(m => m == "get") ? null : new BodyModel
|
||||
{
|
||||
Matcher = bodyMatcher != null ? MatcherMapper.Map(bodyMatcher.Matcher) : null
|
||||
}
|
||||
}).ToList() : null
|
||||
},
|
||||
Response = new ResponseModel
|
||||
{
|
||||
Delay = response.Delay?.Milliseconds
|
||||
Delay = (int?)response.Delay?.TotalMilliseconds
|
||||
}
|
||||
};
|
||||
|
||||
if (methodMatcher?.Methods != null && methodMatcher.Methods.All(m => m != "get") && bodyMatcher?.Matchers != null)
|
||||
{
|
||||
mappingModel.Request.Body = new BodyModel();
|
||||
|
||||
if (bodyMatcher.Matchers.Length == 1)
|
||||
{
|
||||
mappingModel.Request.Body.Matcher = MatcherMapper.Map(bodyMatcher.Matchers[0]);
|
||||
}
|
||||
else if (bodyMatcher.Matchers.Length > 1)
|
||||
{
|
||||
mappingModel.Request.Body.Matchers = MatcherMapper.Map(bodyMatcher.Matchers);
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(response.ProxyUrl))
|
||||
{
|
||||
mappingModel.Response.StatusCode = null;
|
||||
@@ -91,7 +101,7 @@ namespace WireMock.Serialization
|
||||
mappingModel.Response.BodyAsBytes = null;
|
||||
mappingModel.Response.BodyAsFile = null;
|
||||
mappingModel.Response.BodyAsFileIsCached = null;
|
||||
mappingModel.Response.UseTransformer = false;
|
||||
mappingModel.Response.UseTransformer = null;
|
||||
mappingModel.Response.BodyEncoding = null;
|
||||
mappingModel.Response.ProxyUrl = response.ProxyUrl;
|
||||
}
|
||||
@@ -100,7 +110,10 @@ namespace WireMock.Serialization
|
||||
mappingModel.Response.BodyDestination = response.ResponseMessage.BodyDestination;
|
||||
mappingModel.Response.StatusCode = response.ResponseMessage.StatusCode;
|
||||
mappingModel.Response.Headers = Map(response.ResponseMessage.Headers);
|
||||
mappingModel.Response.UseTransformer = response.UseTransformer;
|
||||
if (response.UseTransformer)
|
||||
{
|
||||
mappingModel.Response.UseTransformer = response.UseTransformer;
|
||||
}
|
||||
|
||||
if (response.ResponseMessage.BodyData != null)
|
||||
{
|
||||
@@ -112,7 +125,10 @@ namespace WireMock.Serialization
|
||||
|
||||
case BodyType.Json:
|
||||
mappingModel.Response.BodyAsJson = response.ResponseMessage.BodyData.BodyAsJson;
|
||||
mappingModel.Response.BodyAsJsonIndented = response.ResponseMessage.BodyData.BodyAsJsonIndented;
|
||||
if (response.ResponseMessage.BodyData.BodyAsJsonIndented == true)
|
||||
{
|
||||
mappingModel.Response.BodyAsJsonIndented = response.ResponseMessage.BodyData.BodyAsJsonIndented;
|
||||
}
|
||||
break;
|
||||
|
||||
case BodyType.Bytes:
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
using System;
|
||||
using JetBrains.Annotations;
|
||||
using SimMetrics.Net;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using JetBrains.Annotations;
|
||||
using SimMetrics.Net;
|
||||
using WireMock.Admin.Mappings;
|
||||
using WireMock.Matchers;
|
||||
|
||||
@@ -10,6 +10,11 @@ namespace WireMock.Serialization
|
||||
{
|
||||
internal static class MatcherMapper
|
||||
{
|
||||
public static IMatcher[] Map([CanBeNull] IEnumerable<MatcherModel> matchers)
|
||||
{
|
||||
return matchers?.Select(Map).Where(m => m != null).ToArray();
|
||||
}
|
||||
|
||||
public static IMatcher Map([CanBeNull] MatcherModel matcher)
|
||||
{
|
||||
if (matcher == null)
|
||||
@@ -32,6 +37,10 @@ namespace WireMock.Serialization
|
||||
case "ExactMatcher":
|
||||
return new ExactMatcher(matchBehaviour, stringPatterns);
|
||||
|
||||
case "ExactObjectMatcher":
|
||||
var bytePattern = Convert.FromBase64String(stringPatterns[0]);
|
||||
return new ExactObjectMatcher(matchBehaviour, bytePattern);
|
||||
|
||||
case "RegexMatcher":
|
||||
return new RegexMatcher(matchBehaviour, stringPatterns, matcher.IgnoreCase == true);
|
||||
|
||||
@@ -41,6 +50,9 @@ namespace WireMock.Serialization
|
||||
case "JsonPathMatcher":
|
||||
return new JsonPathMatcher(matchBehaviour, stringPatterns);
|
||||
|
||||
case "JmesPathMatcher":
|
||||
return new JmesPathMatcher(matchBehaviour, stringPatterns);
|
||||
|
||||
case "XPathMatcher":
|
||||
return new XPathMatcher(matchBehaviour, (string)matcher.Pattern);
|
||||
|
||||
@@ -63,7 +75,7 @@ namespace WireMock.Serialization
|
||||
|
||||
public static MatcherModel[] Map([CanBeNull] IEnumerable<IMatcher> matchers)
|
||||
{
|
||||
return matchers?.Select(Map).Where(x => x != null).ToArray();
|
||||
return matchers?.Select(Map).Where(m => m != null).ToArray();
|
||||
}
|
||||
|
||||
public static MatcherModel Map([CanBeNull] IMatcher matcher)
|
||||
@@ -73,20 +85,33 @@ namespace WireMock.Serialization
|
||||
return null;
|
||||
}
|
||||
|
||||
// If the matcher is a IStringMatcher, get the patterns.
|
||||
// If the matcher is a IValueMatcher, get the value (can be string or object).
|
||||
// Else empty array
|
||||
object[] patterns = matcher is IStringMatcher stringMatcher ?
|
||||
stringMatcher.GetPatterns().Cast<object>().ToArray() :
|
||||
matcher is IValueMatcher valueMatcher ? new[] { valueMatcher.Value } :
|
||||
new object[0];
|
||||
bool? ignorecase = matcher is IIgnoreCaseMatcher ignoreCaseMatcher ? ignoreCaseMatcher.IgnoreCase : (bool?)null;
|
||||
object[] patterns = new object[0]; // Default empty array
|
||||
switch (matcher)
|
||||
{
|
||||
// If the matcher is a IStringMatcher, get the patterns.
|
||||
case IStringMatcher stringMatcher:
|
||||
patterns = stringMatcher.GetPatterns().Cast<object>().ToArray();
|
||||
break;
|
||||
|
||||
// If the matcher is a IValueMatcher, get the value (can be string or object).
|
||||
case IValueMatcher valueMatcher:
|
||||
patterns = new[] { valueMatcher.Value };
|
||||
break;
|
||||
|
||||
// If the matcher is a ExactObjectMatcher, get the ValueAsObject or ValueAsBytes.
|
||||
case ExactObjectMatcher exactObjectMatcher:
|
||||
patterns = new[] { exactObjectMatcher.ValueAsObject ?? exactObjectMatcher.ValueAsBytes };
|
||||
break;
|
||||
}
|
||||
|
||||
bool? ignoreCase = matcher is IIgnoreCaseMatcher ignoreCaseMatcher ? ignoreCaseMatcher.IgnoreCase : (bool?)null;
|
||||
|
||||
bool? rejectOnMatch = matcher.MatchBehaviour == MatchBehaviour.RejectOnMatch ? true : (bool?)null;
|
||||
|
||||
return new MatcherModel
|
||||
{
|
||||
RejectOnMatch = rejectOnMatch,
|
||||
IgnoreCase = ignorecase,
|
||||
IgnoreCase = ignoreCase,
|
||||
Name = matcher.Name,
|
||||
Pattern = patterns.Length == 1 ? patterns.First() : null,
|
||||
Patterns = patterns.Length > 1 ? patterns : null
|
||||
|
||||
@@ -34,15 +34,16 @@ namespace WireMock.Server
|
||||
private const int AdminPriority = int.MinValue;
|
||||
private const int ProxyPriority = 1000;
|
||||
private const string ContentTypeJson = "application/json";
|
||||
private const string AdminFiles = "/__admin/files";
|
||||
private const string AdminMappings = "/__admin/mappings";
|
||||
private const string AdminRequests = "/__admin/requests";
|
||||
private const string AdminSettings = "/__admin/settings";
|
||||
private const string AdminScenarios = "/__admin/scenarios";
|
||||
|
||||
private readonly RegexMatcher _adminMappingsGuidPathMatcher = new RegexMatcher(MatchBehaviour.AcceptOnMatch, @"^\/__admin\/mappings\/(\{{0,1}([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}\}{0,1})$");
|
||||
private readonly RegexMatcher _adminRequestsGuidPathMatcher = new RegexMatcher(MatchBehaviour.AcceptOnMatch, @"^\/__admin\/requests\/(\{{0,1}([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}\}{0,1})$");
|
||||
private readonly RegexMatcher _adminMappingsGuidPathMatcher = new RegexMatcher(MatchBehaviour.AcceptOnMatch, @"^\/__admin\/mappings\/([0-9A-Fa-f]{8}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{12})$");
|
||||
private readonly RegexMatcher _adminRequestsGuidPathMatcher = new RegexMatcher(MatchBehaviour.AcceptOnMatch, @"^\/__admin\/requests\/([0-9A-Fa-f]{8}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{12})$");
|
||||
|
||||
private readonly JsonSerializerSettings _settings = new JsonSerializerSettings
|
||||
private readonly JsonSerializerSettings _jsonSerializerSettings = new JsonSerializerSettings
|
||||
{
|
||||
Formatting = Formatting.Indented,
|
||||
NullValueHandling = NullValueHandling.Ignore
|
||||
@@ -97,10 +98,17 @@ namespace WireMock.Server
|
||||
|
||||
// __admin/scenarios/reset
|
||||
Given(Request.Create().WithPath(AdminScenarios + "/reset").UsingPost()).AtPriority(AdminPriority).RespondWith(new DynamicResponseProvider(ScenariosReset));
|
||||
|
||||
// __admin/files/{filename}
|
||||
Given(Request.Create().WithPath(_adminFilesFilenamePathMatcher).UsingPost()).AtPriority(AdminPriority).RespondWith(new DynamicResponseProvider(FilePost));
|
||||
Given(Request.Create().WithPath(_adminFilesFilenamePathMatcher).UsingPut()).AtPriority(AdminPriority).RespondWith(new DynamicResponseProvider(FilePut));
|
||||
Given(Request.Create().WithPath(_adminFilesFilenamePathMatcher).UsingGet()).AtPriority(AdminPriority).RespondWith(new DynamicResponseProvider(FileGet));
|
||||
Given(Request.Create().WithPath(_adminFilesFilenamePathMatcher).UsingHead()).AtPriority(AdminPriority).RespondWith(new DynamicResponseProvider(FileHead));
|
||||
Given(Request.Create().WithPath(_adminFilesFilenamePathMatcher).UsingDelete()).AtPriority(AdminPriority).RespondWith(new DynamicResponseProvider(FileDelete));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region StaticMappings
|
||||
#region StaticMappings
|
||||
/// <summary>
|
||||
/// Saves the static mappings.
|
||||
/// </summary>
|
||||
@@ -123,18 +131,18 @@ namespace WireMock.Server
|
||||
{
|
||||
if (folder == null)
|
||||
{
|
||||
folder = _fileSystemHandler.GetMappingFolder();
|
||||
folder = _settings.FileSystemHandler.GetMappingFolder();
|
||||
}
|
||||
|
||||
if (!_fileSystemHandler.FolderExists(folder))
|
||||
if (!_settings.FileSystemHandler.FolderExists(folder))
|
||||
{
|
||||
_logger.Info("The Static Mapping folder '{0}' does not exist, reading Static MappingFiles will be skipped.", folder);
|
||||
_settings.Logger.Info("The Static Mapping folder '{0}' does not exist, reading Static MappingFiles will be skipped.", folder);
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (string filename in _fileSystemHandler.EnumerateFiles(folder).OrderBy(f => f))
|
||||
foreach (string filename in _settings.FileSystemHandler.EnumerateFiles(folder).OrderBy(f => f))
|
||||
{
|
||||
_logger.Info("Reading Static MappingFile : '{0}'", filename);
|
||||
_settings.Logger.Info("Reading Static MappingFile : '{0}'", filename);
|
||||
|
||||
try
|
||||
{
|
||||
@@ -142,7 +150,7 @@ namespace WireMock.Server
|
||||
}
|
||||
catch
|
||||
{
|
||||
_logger.Error("Static MappingFile : '{0}' could not be read. This file will be skipped.", filename);
|
||||
_settings.Logger.Error("Static MappingFile : '{0}' could not be read. This file will be skipped.", filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -156,30 +164,36 @@ namespace WireMock.Server
|
||||
{
|
||||
if (folder == null)
|
||||
{
|
||||
folder = _fileSystemHandler.GetMappingFolder();
|
||||
folder = _settings.FileSystemHandler.GetMappingFolder();
|
||||
}
|
||||
|
||||
if (!_fileSystemHandler.FolderExists(folder))
|
||||
if (!_settings.FileSystemHandler.FolderExists(folder))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_logger.Info("Watching folder '{0}' for new, updated and deleted MappingFiles.", folder);
|
||||
_settings.Logger.Info("Watching folder '{0}' for new, updated and deleted MappingFiles.", folder);
|
||||
|
||||
var watcher = new EnhancedFileSystemWatcher(folder, "*.json", EnhancedFileSystemWatcherTimeoutMs);
|
||||
watcher.Created += (sender, args) =>
|
||||
{
|
||||
_logger.Info("New MappingFile created : '{0}'", args.FullPath);
|
||||
ReadStaticMappingAndAddOrUpdate(args.FullPath);
|
||||
_settings.Logger.Info("MappingFile created : '{0}', reading file.", args.FullPath);
|
||||
if (!ReadStaticMappingAndAddOrUpdate(args.FullPath))
|
||||
{
|
||||
_settings.Logger.Error("Unable to read MappingFile '{0}'.", args.FullPath);
|
||||
}
|
||||
};
|
||||
watcher.Changed += (sender, args) =>
|
||||
{
|
||||
_logger.Info("New MappingFile updated : '{0}'", args.FullPath);
|
||||
ReadStaticMappingAndAddOrUpdate(args.FullPath);
|
||||
_settings.Logger.Info("MappingFile updated : '{0}', reading file.", args.FullPath);
|
||||
if (!ReadStaticMappingAndAddOrUpdate(args.FullPath))
|
||||
{
|
||||
_settings.Logger.Error("Unable to read MappingFile '{0}'.", args.FullPath);
|
||||
}
|
||||
};
|
||||
watcher.Deleted += (sender, args) =>
|
||||
{
|
||||
_logger.Info("New MappingFile deleted : '{0}'", args.FullPath);
|
||||
_settings.Logger.Info("MappingFile deleted : '{0}'", args.FullPath);
|
||||
string filenameWithoutExtension = Path.GetFileNameWithoutExtension(args.FullPath);
|
||||
|
||||
if (Guid.TryParse(filenameWithoutExtension, out Guid guidFromFilename))
|
||||
@@ -200,24 +214,31 @@ namespace WireMock.Server
|
||||
/// </summary>
|
||||
/// <param name="path">The path.</param>
|
||||
[PublicAPI]
|
||||
public void ReadStaticMappingAndAddOrUpdate([NotNull] string path)
|
||||
public bool ReadStaticMappingAndAddOrUpdate([NotNull] string path)
|
||||
{
|
||||
Check.NotNull(path, nameof(path));
|
||||
|
||||
string filenameWithoutExtension = Path.GetFileNameWithoutExtension(path);
|
||||
|
||||
var mappingModels = DeserializeObjectToArray<MappingModel>(JsonConvert.DeserializeObject(_fileSystemHandler.ReadMappingFile(path)));
|
||||
foreach (var mappingModel in mappingModels)
|
||||
if (FileHelper.TryReadMappingFileWithRetryAndDelay(_settings.FileSystemHandler, path, out string value))
|
||||
{
|
||||
if (mappingModels.Length == 1 && Guid.TryParse(filenameWithoutExtension, out Guid guidFromFilename))
|
||||
var mappingModels = DeserializeObjectToArray<MappingModel>(JsonConvert.DeserializeObject(value));
|
||||
foreach (var mappingModel in mappingModels)
|
||||
{
|
||||
DeserializeAndAddOrUpdateMapping(mappingModel, guidFromFilename, path);
|
||||
}
|
||||
else
|
||||
{
|
||||
DeserializeAndAddOrUpdateMapping(mappingModel, null, path);
|
||||
if (mappingModels.Length == 1 && Guid.TryParse(filenameWithoutExtension, out Guid guidFromFilename))
|
||||
{
|
||||
DeserializeAndAddOrUpdateMapping(mappingModel, guidFromFilename, path);
|
||||
}
|
||||
else
|
||||
{
|
||||
DeserializeAndAddOrUpdateMapping(mappingModel, null, path);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
#endregion
|
||||
|
||||
@@ -234,23 +255,23 @@ namespace WireMock.Server
|
||||
respondProvider.AtPriority(ProxyPriority);
|
||||
}
|
||||
|
||||
respondProvider.RespondWith(new ProxyAsyncResponseProvider(ProxyAndRecordAsync, settings.ProxyAndRecordSettings));
|
||||
respondProvider.RespondWith(new ProxyAsyncResponseProvider(ProxyAndRecordAsync, settings));
|
||||
}
|
||||
|
||||
private async Task<ResponseMessage> ProxyAndRecordAsync(RequestMessage requestMessage, IProxyAndRecordSettings settings)
|
||||
private async Task<ResponseMessage> ProxyAndRecordAsync(RequestMessage requestMessage, IFluentMockServerSettings settings)
|
||||
{
|
||||
var requestUri = new Uri(requestMessage.Url);
|
||||
var proxyUri = new Uri(settings.Url);
|
||||
var proxyUri = new Uri(settings.ProxyAndRecordSettings.Url);
|
||||
var proxyUriWithRequestPathAndQuery = new Uri(proxyUri, requestUri.PathAndQuery);
|
||||
|
||||
var responseMessage = await HttpClientHelper.SendAsync(_httpClientForProxy, requestMessage, proxyUriWithRequestPathAndQuery.AbsoluteUri);
|
||||
|
||||
if (settings.SaveMapping)
|
||||
if (settings.ProxyAndRecordSettings.SaveMapping)
|
||||
{
|
||||
var mapping = ToMapping(requestMessage, responseMessage, settings.BlackListedHeaders ?? new string[] { });
|
||||
var mapping = ToMapping(requestMessage, responseMessage, settings.ProxyAndRecordSettings.BlackListedHeaders ?? new string[] { });
|
||||
_options.Mappings.TryAdd(mapping.Guid, mapping);
|
||||
|
||||
if (settings.SaveMappingToFile)
|
||||
if (settings.ProxyAndRecordSettings.SaveMappingToFile)
|
||||
{
|
||||
SaveMappingToFile(mapping);
|
||||
}
|
||||
@@ -265,7 +286,7 @@ namespace WireMock.Server
|
||||
request.WithPath(requestMessage.Path);
|
||||
request.UsingMethod(requestMessage.Method);
|
||||
|
||||
requestMessage.Query.Loop((key, value) => request.WithParam(key, value.ToArray()));
|
||||
requestMessage.Query.Loop((key, value) => request.WithParam(key, false, value.ToArray()));
|
||||
requestMessage.Cookies.Loop((key, value) => request.WithCookie(key, value));
|
||||
|
||||
var allBlackListedHeaders = new List<string>(blacklistedHeaders) { "Cookie" };
|
||||
@@ -277,18 +298,24 @@ namespace WireMock.Server
|
||||
}
|
||||
});
|
||||
|
||||
if (requestMessage.BodyData?.DetectedBodyType == BodyType.Json)
|
||||
switch (requestMessage.BodyData?.DetectedBodyType)
|
||||
{
|
||||
request.WithBody(new JsonMatcher(MatchBehaviour.AcceptOnMatch, requestMessage.BodyData.BodyAsJson));
|
||||
}
|
||||
else if (requestMessage.BodyData?.DetectedBodyType == BodyType.String)
|
||||
{
|
||||
request.WithBody(new ExactMatcher(MatchBehaviour.AcceptOnMatch, requestMessage.BodyData.BodyAsString));
|
||||
case BodyType.Json:
|
||||
request.WithBody(new JsonMatcher(MatchBehaviour.AcceptOnMatch, requestMessage.BodyData.BodyAsJson));
|
||||
break;
|
||||
|
||||
case BodyType.String:
|
||||
request.WithBody(new ExactMatcher(MatchBehaviour.AcceptOnMatch, requestMessage.BodyData.BodyAsString));
|
||||
break;
|
||||
|
||||
case BodyType.Bytes:
|
||||
request.WithBody(new ExactObjectMatcher(MatchBehaviour.AcceptOnMatch, requestMessage.BodyData.BodyAsBytes));
|
||||
break;
|
||||
}
|
||||
|
||||
var response = Response.Create(responseMessage);
|
||||
|
||||
return new Mapping(Guid.NewGuid(), string.Empty, null, request, response, 0, null, null, null);
|
||||
return new Mapping(Guid.NewGuid(), string.Empty, null, _settings, request, response, 0, null, null, null);
|
||||
}
|
||||
#endregion
|
||||
|
||||
@@ -334,7 +361,7 @@ namespace WireMock.Server
|
||||
|
||||
if (mapping == null)
|
||||
{
|
||||
_logger.Warn("HttpStatusCode set to 404 : Mapping not found");
|
||||
_settings.Logger.Warn("HttpStatusCode set to 404 : Mapping not found");
|
||||
return ResponseMessageBuilder.Create("Mapping not found", 404);
|
||||
}
|
||||
|
||||
@@ -378,12 +405,12 @@ namespace WireMock.Server
|
||||
{
|
||||
if (folder == null)
|
||||
{
|
||||
folder = _fileSystemHandler.GetMappingFolder();
|
||||
folder = _settings.FileSystemHandler.GetMappingFolder();
|
||||
}
|
||||
|
||||
if (!_fileSystemHandler.FolderExists(folder))
|
||||
if (!_settings.FileSystemHandler.FolderExists(folder))
|
||||
{
|
||||
_fileSystemHandler.CreateFolder(folder);
|
||||
_settings.FileSystemHandler.CreateFolder(folder);
|
||||
}
|
||||
|
||||
var model = MappingConverter.ToMappingModel(mapping);
|
||||
@@ -391,26 +418,23 @@ namespace WireMock.Server
|
||||
|
||||
string path = Path.Combine(folder, filename);
|
||||
|
||||
_logger.Info("Saving Mapping file {0}", filename);
|
||||
_settings.Logger.Info("Saving Mapping file {0}", filename);
|
||||
|
||||
_fileSystemHandler.WriteMappingFile(path, JsonConvert.SerializeObject(model, _settings));
|
||||
_settings.FileSystemHandler.WriteMappingFile(path, JsonConvert.SerializeObject(model, _jsonSerializerSettings));
|
||||
}
|
||||
|
||||
private static string SanitizeFileName(string name, char replaceChar = '_')
|
||||
{
|
||||
return Path.GetInvalidFileNameChars().Aggregate(name, (current, c) => current.Replace(c, replaceChar));
|
||||
}
|
||||
private IEnumerable<MappingModel> ToMappingModels()
|
||||
{
|
||||
return Mappings.Where(m => !m.IsAdminInterface).Select(MappingConverter.ToMappingModel);
|
||||
}
|
||||
|
||||
private ResponseMessage MappingsGet(RequestMessage requestMessage)
|
||||
{
|
||||
var result = new List<MappingModel>();
|
||||
foreach (var mapping in Mappings.Where(m => !m.IsAdminInterface))
|
||||
{
|
||||
var model = MappingConverter.ToMappingModel(mapping);
|
||||
result.Add(model);
|
||||
}
|
||||
|
||||
return ToJson(result);
|
||||
return ToJson(ToMappingModels());
|
||||
}
|
||||
|
||||
private ResponseMessage MappingsPost(RequestMessage requestMessage)
|
||||
@@ -433,12 +457,12 @@ namespace WireMock.Server
|
||||
}
|
||||
catch (ArgumentException a)
|
||||
{
|
||||
_logger.Error("HttpStatusCode set to 400 {0}", a);
|
||||
_settings.Logger.Error("HttpStatusCode set to 400 {0}", a);
|
||||
return ResponseMessageBuilder.Create(a.Message, 400);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.Error("HttpStatusCode set to 500 {0}", e);
|
||||
_settings.Logger.Error("HttpStatusCode set to 500 {0}", e);
|
||||
return ResponseMessageBuilder.Create(e.ToString(), 500);
|
||||
}
|
||||
}
|
||||
@@ -457,7 +481,7 @@ namespace WireMock.Server
|
||||
|
||||
var responseBuilder = InitResponseBuilder(mappingModel.Response);
|
||||
|
||||
var respondProvider = Given(requestBuilder);
|
||||
var respondProvider = Given(requestBuilder, mappingModel.SaveToFile == true);
|
||||
|
||||
if (guid != null)
|
||||
{
|
||||
@@ -513,7 +537,7 @@ namespace WireMock.Server
|
||||
|
||||
if (entry == null)
|
||||
{
|
||||
_logger.Warn("HttpStatusCode set to 404 : Request not found");
|
||||
_settings.Logger.Warn("HttpStatusCode set to 404 : Request not found");
|
||||
return ResponseMessageBuilder.Create("Request not found", 404);
|
||||
}
|
||||
|
||||
@@ -656,7 +680,7 @@ namespace WireMock.Server
|
||||
|
||||
if (pathOrUrlRequired && !pathOrUrlmatchersValid)
|
||||
{
|
||||
_logger.Error("Path or Url matcher is missing for this mapping, this mapping will not be added.");
|
||||
_settings.Logger.Error("Path or Url matcher is missing for this mapping, this mapping will not be added.");
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -685,14 +709,18 @@ namespace WireMock.Server
|
||||
{
|
||||
foreach (var paramModel in requestModel.Params.Where(c => c.Matchers != null))
|
||||
{
|
||||
requestBuilder = requestBuilder.WithParam(paramModel.Name, paramModel.Matchers.Select(MatcherMapper.Map).Cast<IStringMatcher>().ToArray());
|
||||
bool ignoreCase = paramModel?.IgnoreCase ?? false;
|
||||
requestBuilder = requestBuilder.WithParam(paramModel.Name, ignoreCase, paramModel.Matchers.Select(MatcherMapper.Map).Cast<IStringMatcher>().ToArray());
|
||||
}
|
||||
}
|
||||
|
||||
if (requestModel.Body?.Matcher != null)
|
||||
{
|
||||
var bodyMatcher = MatcherMapper.Map(requestModel.Body.Matcher);
|
||||
requestBuilder = requestBuilder.WithBody(bodyMatcher);
|
||||
requestBuilder = requestBuilder.WithBody(MatcherMapper.Map(requestModel.Body.Matcher));
|
||||
}
|
||||
else if (requestModel.Body?.Matchers != null)
|
||||
{
|
||||
requestBuilder = requestBuilder.WithBody(MatcherMapper.Map(requestModel.Body.Matchers));
|
||||
}
|
||||
|
||||
return requestBuilder;
|
||||
@@ -707,6 +735,11 @@ namespace WireMock.Server
|
||||
responseBuilder = responseBuilder.WithDelay(responseModel.Delay.Value);
|
||||
}
|
||||
|
||||
if (responseModel.UseTransformer == true)
|
||||
{
|
||||
responseBuilder = responseBuilder.WithTransformer();
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(responseModel.ProxyUrl))
|
||||
{
|
||||
if (string.IsNullOrEmpty(responseModel.X509Certificate2ThumbprintOrSubjectName))
|
||||
@@ -763,11 +796,6 @@ namespace WireMock.Server
|
||||
responseBuilder = responseBuilder.WithBodyFromFile(responseModel.BodyAsFile);
|
||||
}
|
||||
|
||||
if (responseModel.UseTransformer)
|
||||
{
|
||||
responseBuilder = responseBuilder.WithTransformer();
|
||||
}
|
||||
|
||||
return responseBuilder;
|
||||
}
|
||||
|
||||
@@ -778,7 +806,7 @@ namespace WireMock.Server
|
||||
BodyData = new BodyData
|
||||
{
|
||||
DetectedBodyType = BodyType.String,
|
||||
BodyAsString = JsonConvert.SerializeObject(result, keepNullValues ? _settingsIncludeNullValues : _settings)
|
||||
BodyAsString = JsonConvert.SerializeObject(result, keepNullValues ? _settingsIncludeNullValues : _jsonSerializerSettings)
|
||||
},
|
||||
StatusCode = 200,
|
||||
Headers = new Dictionary<string, WireMockList<string>> { { HttpKnownHeaderNames.ContentType, new WireMockList<string>(ContentTypeJson) } }
|
||||
|
||||
114
src/WireMock.Net/Server/FluentMockServer.AdminFiles.cs
Normal file
114
src/WireMock.Net/Server/FluentMockServer.AdminFiles.cs
Normal file
@@ -0,0 +1,114 @@
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using WireMock.Matchers;
|
||||
using WireMock.Util;
|
||||
|
||||
namespace WireMock.Server
|
||||
{
|
||||
public partial class FluentMockServer
|
||||
{
|
||||
private readonly RegexMatcher _adminFilesFilenamePathMatcher = new RegexMatcher(MatchBehaviour.AcceptOnMatch, @"^\/__admin\/files\/.*$");
|
||||
private static readonly Encoding[] FileBodyIsString = { Encoding.UTF8, Encoding.ASCII };
|
||||
|
||||
#region Files/{filename}
|
||||
private ResponseMessage FilePost(RequestMessage requestMessage)
|
||||
{
|
||||
string filename = GetFileNameFromRequestMessage(requestMessage);
|
||||
|
||||
string mappingFolder = _settings.FileSystemHandler.GetMappingFolder();
|
||||
if (!_settings.FileSystemHandler.FolderExists(mappingFolder))
|
||||
{
|
||||
_settings.FileSystemHandler.CreateFolder(mappingFolder);
|
||||
}
|
||||
|
||||
_settings.FileSystemHandler.WriteFile(filename, requestMessage.BodyAsBytes);
|
||||
|
||||
return ResponseMessageBuilder.Create("File created");
|
||||
}
|
||||
|
||||
private ResponseMessage FilePut(RequestMessage requestMessage)
|
||||
{
|
||||
string filename = GetFileNameFromRequestMessage(requestMessage);
|
||||
|
||||
if (!_settings.FileSystemHandler.FileExists(filename))
|
||||
{
|
||||
_settings.Logger.Info("The file '{0}' does not exist, updating file will be skipped.", filename);
|
||||
return ResponseMessageBuilder.Create("File is not found", 404);
|
||||
}
|
||||
|
||||
_settings.FileSystemHandler.WriteFile(filename, requestMessage.BodyAsBytes);
|
||||
|
||||
return ResponseMessageBuilder.Create("File updated");
|
||||
}
|
||||
|
||||
private ResponseMessage FileGet(RequestMessage requestMessage)
|
||||
{
|
||||
string filename = GetFileNameFromRequestMessage(requestMessage);
|
||||
|
||||
if (!_settings.FileSystemHandler.FileExists(filename))
|
||||
{
|
||||
_settings.Logger.Info("The file '{0}' does not exist.", filename);
|
||||
return ResponseMessageBuilder.Create("File is not found", 404);
|
||||
}
|
||||
|
||||
byte[] bytes = _settings.FileSystemHandler.ReadFile(filename);
|
||||
var response = new ResponseMessage
|
||||
{
|
||||
StatusCode = 200,
|
||||
BodyData = new BodyData
|
||||
{
|
||||
BodyAsBytes = bytes,
|
||||
DetectedBodyType = BodyType.Bytes,
|
||||
DetectedBodyTypeFromContentType = BodyType.None
|
||||
}
|
||||
};
|
||||
|
||||
if (BytesEncodingUtils.TryGetEncoding(bytes, out Encoding encoding) && FileBodyIsString.Select(x => x.Equals(encoding)).Any())
|
||||
{
|
||||
response.BodyData.DetectedBodyType = BodyType.String;
|
||||
response.BodyData.BodyAsString = encoding.GetString(bytes);
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if file exists.
|
||||
/// Note: Response is returned with no body as a head request doesn't accept a body, only the status code.
|
||||
/// </summary>
|
||||
/// <param name="requestMessage">The request message.</param>
|
||||
private ResponseMessage FileHead(RequestMessage requestMessage)
|
||||
{
|
||||
string filename = GetFileNameFromRequestMessage(requestMessage);
|
||||
|
||||
if (!_settings.FileSystemHandler.FileExists(filename))
|
||||
{
|
||||
_settings.Logger.Info("The file '{0}' does not exist.", filename);
|
||||
return ResponseMessageBuilder.Create(404);
|
||||
}
|
||||
|
||||
return ResponseMessageBuilder.Create(204);
|
||||
}
|
||||
|
||||
private ResponseMessage FileDelete(RequestMessage requestMessage)
|
||||
{
|
||||
string filename = GetFileNameFromRequestMessage(requestMessage);
|
||||
|
||||
if (!_settings.FileSystemHandler.FileExists(filename))
|
||||
{
|
||||
_settings.Logger.Info("The file '{0}' does not exist.", filename);
|
||||
return ResponseMessageBuilder.Create("File is not deleted", 404);
|
||||
}
|
||||
|
||||
_settings.FileSystemHandler.DeleteFile(filename);
|
||||
return ResponseMessageBuilder.Create("File deleted.");
|
||||
}
|
||||
|
||||
private string GetFileNameFromRequestMessage(RequestMessage requestMessage)
|
||||
{
|
||||
return Path.GetFileName(requestMessage.Path.Substring(AdminFiles.Length + 1));
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,12 @@
|
||||
using JetBrains.Annotations;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using Newtonsoft.Json;
|
||||
using WireMock.Admin.Mappings;
|
||||
using WireMock.Exceptions;
|
||||
using WireMock.Handlers;
|
||||
using WireMock.Logging;
|
||||
@@ -27,8 +28,7 @@ namespace WireMock.Server
|
||||
{
|
||||
private const int ServerStartDelayInMs = 100;
|
||||
|
||||
private readonly IWireMockLogger _logger;
|
||||
private readonly IFileSystemHandler _fileSystemHandler;
|
||||
private readonly IFluentMockServerSettings _settings;
|
||||
private readonly IOwinSelfHost _httpServer;
|
||||
private readonly IWireMockMiddlewareOptions _options = new WireMockMiddlewareOptions();
|
||||
|
||||
@@ -56,6 +56,12 @@ namespace WireMock.Server
|
||||
[PublicAPI]
|
||||
public IEnumerable<IMapping> Mappings => _options.Mappings.Values.ToArray();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the mappings as MappingModels.
|
||||
/// </summary>
|
||||
[PublicAPI]
|
||||
public IEnumerable<MappingModel> MappingModels => ToMappingModels();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the scenarios.
|
||||
/// </summary>
|
||||
@@ -92,7 +98,7 @@ namespace WireMock.Server
|
||||
/// <param name="settings">The FluentMockServerSettings.</param>
|
||||
/// <returns>The <see cref="FluentMockServer"/>.</returns>
|
||||
[PublicAPI]
|
||||
public static FluentMockServer Start(IFluentMockServerSettings settings)
|
||||
public static FluentMockServer Start([NotNull] IFluentMockServerSettings settings)
|
||||
{
|
||||
Check.NotNull(settings, nameof(settings));
|
||||
|
||||
@@ -185,13 +191,14 @@ namespace WireMock.Server
|
||||
|
||||
private FluentMockServer(IFluentMockServerSettings settings)
|
||||
{
|
||||
settings.Logger = settings.Logger ?? new WireMockConsoleLogger();
|
||||
_settings = settings;
|
||||
|
||||
_logger = settings.Logger;
|
||||
_fileSystemHandler = settings.FileSystemHandler ?? new LocalFileSystemHandler();
|
||||
// Set default values if not provided
|
||||
_settings.Logger = settings.Logger ?? new WireMockNullLogger();
|
||||
_settings.FileSystemHandler = settings.FileSystemHandler ?? new LocalFileSystemHandler();
|
||||
|
||||
_logger.Info("WireMock.Net by Stef Heyenrath (https://github.com/WireMock-Net/WireMock.Net)");
|
||||
_logger.Debug("WireMock.Net server settings {0}", JsonConvert.SerializeObject(settings, Formatting.Indented));
|
||||
_settings.Logger.Info("WireMock.Net by Stef Heyenrath (https://github.com/WireMock-Net/WireMock.Net)");
|
||||
_settings.Logger.Debug("WireMock.Net server settings {0}", JsonConvert.SerializeObject(settings, Formatting.Indented));
|
||||
|
||||
if (settings.Urls != null)
|
||||
{
|
||||
@@ -203,10 +210,10 @@ namespace WireMock.Server
|
||||
Urls = new[] { $"{(settings.UseSSL == true ? "https" : "http")}://localhost:{port}" };
|
||||
}
|
||||
|
||||
_options.FileSystemHandler = settings.FileSystemHandler;
|
||||
_options.FileSystemHandler = _settings.FileSystemHandler;
|
||||
_options.PreWireMockMiddlewareInit = settings.PreWireMockMiddlewareInit;
|
||||
_options.PostWireMockMiddlewareInit = settings.PostWireMockMiddlewareInit;
|
||||
_options.Logger = _logger;
|
||||
_options.Logger = _settings.Logger;
|
||||
|
||||
#if USE_ASPNETCORE
|
||||
_httpServer = new AspNetCoreSelfHost(_options, Urls);
|
||||
@@ -369,7 +376,7 @@ namespace WireMock.Server
|
||||
[PublicAPI]
|
||||
public void AllowPartialMapping(bool allow = true)
|
||||
{
|
||||
_logger.Info("AllowPartialMapping is set to {0}", allow);
|
||||
_settings.Logger.Info("AllowPartialMapping is set to {0}", allow);
|
||||
_options.AllowPartialMapping = allow;
|
||||
}
|
||||
|
||||
@@ -430,14 +437,15 @@ namespace WireMock.Server
|
||||
/// The given.
|
||||
/// </summary>
|
||||
/// <param name="requestMatcher">The request matcher.</param>
|
||||
/// <param name="saveToFile">Optional boolean to indicate if this mapping should be saved as static mapping file.</param>
|
||||
/// <returns>The <see cref="IRespondWithAProvider"/>.</returns>
|
||||
[PublicAPI]
|
||||
public IRespondWithAProvider Given(IRequestMatcher requestMatcher)
|
||||
public IRespondWithAProvider Given(IRequestMatcher requestMatcher, bool saveToFile = false)
|
||||
{
|
||||
return new RespondWithAProvider(RegisterMapping, requestMatcher);
|
||||
return new RespondWithAProvider(RegisterMapping, requestMatcher, _settings, saveToFile);
|
||||
}
|
||||
|
||||
private void RegisterMapping(IMapping mapping)
|
||||
private void RegisterMapping(IMapping mapping, bool saveToFile)
|
||||
{
|
||||
// Check a mapping exists with the same Guid, if so, replace it.
|
||||
if (_options.Mappings.ContainsKey(mapping.Guid))
|
||||
@@ -448,6 +456,11 @@ namespace WireMock.Server
|
||||
{
|
||||
_options.Mappings.TryAdd(mapping.Guid, mapping);
|
||||
}
|
||||
|
||||
if (saveToFile)
|
||||
{
|
||||
SaveMappingToFile(mapping);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using WireMock.Matchers.Request;
|
||||
using WireMock.ResponseProviders;
|
||||
using WireMock.Settings;
|
||||
|
||||
namespace WireMock.Server
|
||||
{
|
||||
@@ -17,6 +18,8 @@ namespace WireMock.Server
|
||||
private string _scenario;
|
||||
private readonly RegistrationCallback _registrationCallback;
|
||||
private readonly IRequestMatcher _requestMatcher;
|
||||
private readonly IFluentMockServerSettings _settings;
|
||||
private readonly bool _saveToFile;
|
||||
|
||||
public Guid Guid { get; private set; } = Guid.NewGuid();
|
||||
|
||||
@@ -25,10 +28,14 @@ namespace WireMock.Server
|
||||
/// </summary>
|
||||
/// <param name="registrationCallback">The registration callback.</param>
|
||||
/// <param name="requestMatcher">The request matcher.</param>
|
||||
public RespondWithAProvider(RegistrationCallback registrationCallback, IRequestMatcher requestMatcher)
|
||||
/// <param name="settings">The FluentMockServerSettings.</param>
|
||||
/// <param name="saveToFile">Optional boolean to indicate if this mapping should be saved as static mapping file.</param>
|
||||
public RespondWithAProvider(RegistrationCallback registrationCallback, IRequestMatcher requestMatcher, IFluentMockServerSettings settings, bool saveToFile = false)
|
||||
{
|
||||
_registrationCallback = registrationCallback;
|
||||
_requestMatcher = requestMatcher;
|
||||
_settings = settings;
|
||||
_saveToFile = saveToFile;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -37,7 +44,7 @@ namespace WireMock.Server
|
||||
/// <param name="provider">The provider.</param>
|
||||
public void RespondWith(IResponseProvider provider)
|
||||
{
|
||||
_registrationCallback(new Mapping(Guid, _title, _path, _requestMatcher, provider, _priority, _scenario, _executionConditionState, _nextState));
|
||||
_registrationCallback(new Mapping(Guid, _title, _path, _settings, _requestMatcher, provider, _priority, _scenario, _executionConditionState, _nextState), _saveToFile);
|
||||
}
|
||||
|
||||
/// <see cref="IRespondWithAProvider.WithGuid(string)"/>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using HandlebarsDotNet;
|
||||
using JetBrains.Annotations;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using WireMock.Handlers;
|
||||
using WireMock.Logging;
|
||||
|
||||
@@ -82,6 +83,11 @@ namespace WireMock.Settings
|
||||
/// <inheritdoc cref="IFluentMockServerSettings.FileSystemHandler"/>
|
||||
[PublicAPI]
|
||||
[JsonIgnore]
|
||||
public IFileSystemHandler FileSystemHandler { get; set; } = new LocalFileSystemHandler();
|
||||
public IFileSystemHandler FileSystemHandler { get; set; }
|
||||
|
||||
/// <inheritdoc cref="IFluentMockServerSettings.HandlebarsRegistrationCallback"/>
|
||||
[PublicAPI]
|
||||
[JsonIgnore]
|
||||
public Action<IHandlebars, IFileSystemHandler> HandlebarsRegistrationCallback { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using HandlebarsDotNet;
|
||||
using JetBrains.Annotations;
|
||||
using System;
|
||||
using WireMock.Handlers;
|
||||
using WireMock.Logging;
|
||||
|
||||
@@ -24,7 +25,7 @@ namespace WireMock.Settings
|
||||
bool? UseSSL { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets wether to start admin interface.
|
||||
/// Gets or sets whether to start admin interface.
|
||||
/// </summary>
|
||||
[PublicAPI]
|
||||
bool? StartAdminInterface { get; set; }
|
||||
@@ -112,5 +113,11 @@ namespace WireMock.Settings
|
||||
/// </summary>
|
||||
[PublicAPI]
|
||||
IFileSystemHandler FileSystemHandler { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Action which can be used to add additional is Handlebar registrations. [Optional]
|
||||
/// </summary>
|
||||
[PublicAPI]
|
||||
Action<IHandlebars, IFileSystemHandler> HandlebarsRegistrationCallback { get; set; }
|
||||
}
|
||||
}
|
||||
41
src/WireMock.Net/Transformers/HandleBarsFile.cs
Normal file
41
src/WireMock.Net/Transformers/HandleBarsFile.cs
Normal file
@@ -0,0 +1,41 @@
|
||||
using HandlebarsDotNet;
|
||||
using System;
|
||||
using WireMock.Handlers;
|
||||
using WireMock.Validation;
|
||||
|
||||
namespace WireMock.Transformers
|
||||
{
|
||||
internal static class HandleBarsFile
|
||||
{
|
||||
public static void Register(IHandlebars handlebarsContext, IFileSystemHandler fileSystemHandler)
|
||||
{
|
||||
handlebarsContext.RegisterHelper("File", (writer, context, arguments) =>
|
||||
{
|
||||
string value = ParseArgumentAndReadFileFragment(handlebarsContext, context, fileSystemHandler, arguments);
|
||||
writer.Write(value);
|
||||
});
|
||||
|
||||
handlebarsContext.RegisterHelper("File", (writer, options, context, arguments) =>
|
||||
{
|
||||
string value = ParseArgumentAndReadFileFragment(handlebarsContext, context, fileSystemHandler, arguments);
|
||||
options.Template(writer, value);
|
||||
});
|
||||
}
|
||||
|
||||
private static string ParseArgumentAndReadFileFragment(IHandlebars handlebarsContext, dynamic context, IFileSystemHandler fileSystemHandler, object[] arguments)
|
||||
{
|
||||
Check.Condition(arguments, args => args.Length == 1, nameof(arguments));
|
||||
Check.NotNull(arguments[0], "arguments[0]");
|
||||
|
||||
switch (arguments[0])
|
||||
{
|
||||
case string path:
|
||||
var templateFunc = handlebarsContext.Compile(path);
|
||||
string transformed = templateFunc(context);
|
||||
return fileSystemHandler.ReadResponseBodyAsString(transformed);
|
||||
}
|
||||
|
||||
throw new NotSupportedException($"The value '{arguments[0]}' with type '{arguments[0]?.GetType()}' cannot be used in Handlebars File.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,11 @@
|
||||
using HandlebarsDotNet;
|
||||
using WireMock.Handlers;
|
||||
|
||||
namespace WireMock.Transformers
|
||||
{
|
||||
internal static class HandlebarsHelpers
|
||||
{
|
||||
public static void Register(IHandlebars handlebarsContext)
|
||||
public static void Register(IHandlebars handlebarsContext, IFileSystemHandler fileSystemHandler)
|
||||
{
|
||||
HandleBarsRegex.Register(handlebarsContext);
|
||||
|
||||
@@ -15,6 +16,8 @@ namespace WireMock.Transformers
|
||||
HandleBarsRandom.Register(handlebarsContext);
|
||||
|
||||
HandleBarsXeger.Register(handlebarsContext);
|
||||
|
||||
HandleBarsFile.Register(handlebarsContext, fileSystemHandler);
|
||||
}
|
||||
}
|
||||
}
|
||||
34
src/WireMock.Net/Transformers/HandlebarsContextFactory.cs
Normal file
34
src/WireMock.Net/Transformers/HandlebarsContextFactory.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
using HandlebarsDotNet;
|
||||
using System;
|
||||
using WireMock.Handlers;
|
||||
|
||||
namespace WireMock.Transformers
|
||||
{
|
||||
internal class HandlebarsContextFactory : IHandlebarsContextFactory
|
||||
{
|
||||
private static readonly HandlebarsConfiguration HandlebarsConfiguration = new HandlebarsConfiguration
|
||||
{
|
||||
UnresolvedBindingFormatter = "{0}"
|
||||
};
|
||||
|
||||
private readonly IFileSystemHandler _fileSystemHandler;
|
||||
private readonly Action<IHandlebars, IFileSystemHandler> _action;
|
||||
|
||||
public HandlebarsContextFactory(IFileSystemHandler fileSystemHandler, Action<IHandlebars, IFileSystemHandler> action)
|
||||
{
|
||||
_fileSystemHandler = fileSystemHandler;
|
||||
_action = action;
|
||||
}
|
||||
|
||||
public IHandlebars Create()
|
||||
{
|
||||
var handlebarsContext = Handlebars.Create(HandlebarsConfiguration);
|
||||
|
||||
HandlebarsHelpers.Register(handlebarsContext, _fileSystemHandler);
|
||||
|
||||
_action?.Invoke(handlebarsContext, _fileSystemHandler);
|
||||
|
||||
return handlebarsContext;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
using HandlebarsDotNet;
|
||||
|
||||
namespace WireMock.Transformers
|
||||
{
|
||||
interface IHandlebarsContextFactory
|
||||
{
|
||||
IHandlebars Create();
|
||||
}
|
||||
}
|
||||
@@ -1,55 +1,57 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using HandlebarsDotNet;
|
||||
using HandlebarsDotNet;
|
||||
using JetBrains.Annotations;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using WireMock.Util;
|
||||
using WireMock.Validation;
|
||||
|
||||
namespace WireMock.Transformers
|
||||
{
|
||||
internal static class ResponseMessageTransformer
|
||||
internal class ResponseMessageTransformer
|
||||
{
|
||||
private static readonly HandlebarsConfiguration HandlebarsConfiguration = new HandlebarsConfiguration
|
||||
{
|
||||
UnresolvedBindingFormatter = "{0}"
|
||||
};
|
||||
private readonly IHandlebarsContextFactory _factory;
|
||||
|
||||
private static readonly IHandlebars HandlebarsContext = Handlebars.Create(HandlebarsConfiguration);
|
||||
|
||||
static ResponseMessageTransformer()
|
||||
public ResponseMessageTransformer([NotNull] IHandlebarsContextFactory factory)
|
||||
{
|
||||
HandlebarsHelpers.Register(HandlebarsContext);
|
||||
Check.NotNull(factory, nameof(factory));
|
||||
|
||||
_factory = factory;
|
||||
}
|
||||
|
||||
public static ResponseMessage Transform(RequestMessage requestMessage, ResponseMessage original)
|
||||
public ResponseMessage Transform(RequestMessage requestMessage, ResponseMessage original)
|
||||
{
|
||||
bool bodyIsJson = original.BodyData.DetectedBodyType == BodyType.Json;
|
||||
var responseMessage = new ResponseMessage { StatusCode = original.StatusCode };
|
||||
var handlebarsContext = _factory.Create();
|
||||
|
||||
if (!bodyIsJson)
|
||||
{
|
||||
responseMessage.BodyOriginal = original.BodyData.BodyAsString;
|
||||
}
|
||||
var responseMessage = new ResponseMessage { StatusCode = original.StatusCode };
|
||||
|
||||
var template = new { request = requestMessage };
|
||||
|
||||
if (!bodyIsJson)
|
||||
switch (original.BodyData.DetectedBodyType)
|
||||
{
|
||||
TransformBodyAsString(template, original, responseMessage);
|
||||
}
|
||||
else
|
||||
{
|
||||
TransformBodyAsJson(template, original, responseMessage);
|
||||
case BodyType.Json:
|
||||
TransformBodyAsJson(handlebarsContext, template, original, responseMessage);
|
||||
break;
|
||||
|
||||
case BodyType.File:
|
||||
TransformBodyAsFile(handlebarsContext, template, original, responseMessage);
|
||||
break;
|
||||
|
||||
case BodyType.String:
|
||||
responseMessage.BodyOriginal = original.BodyData.BodyAsString;
|
||||
TransformBodyAsString(handlebarsContext, template, original, responseMessage);
|
||||
break;
|
||||
}
|
||||
|
||||
// Headers
|
||||
var newHeaders = new Dictionary<string, WireMockList<string>>();
|
||||
foreach (var header in original.Headers)
|
||||
{
|
||||
var templateHeaderKey = HandlebarsContext.Compile(header.Key);
|
||||
var templateHeaderKey = handlebarsContext.Compile(header.Key);
|
||||
var templateHeaderValues = header.Value
|
||||
.Select(HandlebarsContext.Compile)
|
||||
.Select(handlebarsContext.Compile)
|
||||
.Select(func => func(template))
|
||||
.ToArray();
|
||||
|
||||
@@ -61,13 +63,13 @@ namespace WireMock.Transformers
|
||||
return responseMessage;
|
||||
}
|
||||
|
||||
private static void TransformBodyAsJson(object template, ResponseMessage original, ResponseMessage responseMessage)
|
||||
private static void TransformBodyAsJson(IHandlebars handlebarsContext, object template, ResponseMessage original, ResponseMessage responseMessage)
|
||||
{
|
||||
JToken jToken;
|
||||
switch (original.BodyData.BodyAsJson)
|
||||
{
|
||||
case JObject bodyAsJObject:
|
||||
jToken = bodyAsJObject;
|
||||
jToken = bodyAsJObject.DeepClone();
|
||||
break;
|
||||
|
||||
case Array bodyAsArray:
|
||||
@@ -79,7 +81,7 @@ namespace WireMock.Transformers
|
||||
break;
|
||||
}
|
||||
|
||||
WalkNode(jToken, template);
|
||||
WalkNode(handlebarsContext, jToken, template);
|
||||
|
||||
responseMessage.BodyData = new BodyData
|
||||
{
|
||||
@@ -89,14 +91,14 @@ namespace WireMock.Transformers
|
||||
};
|
||||
}
|
||||
|
||||
private static void WalkNode(JToken node, object template)
|
||||
private static void WalkNode(IHandlebars handlebarsContext, JToken node, object context)
|
||||
{
|
||||
if (node.Type == JTokenType.Object)
|
||||
{
|
||||
// In case of Object, loop all children. Do a ToArray() to avoid `Collection was modified` exceptions.
|
||||
foreach (JProperty child in node.Children<JProperty>().ToArray())
|
||||
{
|
||||
WalkNode(child.Value, template);
|
||||
WalkNode(handlebarsContext, child.Value, context);
|
||||
}
|
||||
}
|
||||
else if (node.Type == JTokenType.Array)
|
||||
@@ -104,7 +106,7 @@ namespace WireMock.Transformers
|
||||
// In case of Array, loop all items. Do a ToArray() to avoid `Collection was modified` exceptions.
|
||||
foreach (JToken child in node.Children().ToArray())
|
||||
{
|
||||
WalkNode(child, template);
|
||||
WalkNode(handlebarsContext, child, context);
|
||||
}
|
||||
}
|
||||
else if (node.Type == JTokenType.String)
|
||||
@@ -116,8 +118,8 @@ namespace WireMock.Transformers
|
||||
return;
|
||||
}
|
||||
|
||||
var templateForStringValue = HandlebarsContext.Compile(stringValue);
|
||||
string transformedString = templateForStringValue(template);
|
||||
var templateForStringValue = handlebarsContext.Compile(stringValue);
|
||||
string transformedString = templateForStringValue(context);
|
||||
if (!string.Equals(stringValue, transformedString))
|
||||
{
|
||||
ReplaceNodeValue(node, transformedString);
|
||||
@@ -148,16 +150,28 @@ namespace WireMock.Transformers
|
||||
node.Replace(value);
|
||||
}
|
||||
|
||||
private static void TransformBodyAsString(object template, ResponseMessage original, ResponseMessage responseMessage)
|
||||
private static void TransformBodyAsString(IHandlebars handlebarsContext, object template, ResponseMessage original, ResponseMessage responseMessage)
|
||||
{
|
||||
var templateBody = HandlebarsContext.Compile(original.BodyData.BodyAsString);
|
||||
var templateBodyAsString = handlebarsContext.Compile(original.BodyData.BodyAsString);
|
||||
|
||||
responseMessage.BodyData = new BodyData
|
||||
{
|
||||
DetectedBodyType = original.BodyData.DetectedBodyType,
|
||||
DetectedBodyTypeFromContentType = original.BodyData.DetectedBodyTypeFromContentType,
|
||||
BodyAsString = templateBody(template)
|
||||
BodyAsString = templateBodyAsString(template)
|
||||
};
|
||||
}
|
||||
|
||||
private static void TransformBodyAsFile(IHandlebars handlebarsContext, object template, ResponseMessage original, ResponseMessage responseMessage)
|
||||
{
|
||||
var templateBodyAsFile = handlebarsContext.Compile(original.BodyData.BodyAsFile);
|
||||
|
||||
responseMessage.BodyData = new BodyData
|
||||
{
|
||||
DetectedBodyType = original.BodyData.DetectedBodyType,
|
||||
DetectedBodyTypeFromContentType = original.BodyData.DetectedBodyTypeFromContentType,
|
||||
BodyAsFile = templateBodyAsFile(template)
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using MimeKit;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
@@ -14,6 +15,7 @@ namespace WireMock.Util
|
||||
internal static class BodyParser
|
||||
{
|
||||
private static readonly Encoding DefaultEncoding = Encoding.UTF8;
|
||||
private static readonly Encoding[] SupportedBodyAsStringEncodingForMultipart = { Encoding.UTF8, Encoding.ASCII };
|
||||
|
||||
/*
|
||||
HEAD - No defined body semantics.
|
||||
@@ -26,7 +28,18 @@ namespace WireMock.Util
|
||||
CONNECT - No defined body semantics
|
||||
PATCH - Body supported.
|
||||
*/
|
||||
private static readonly string[] AllowedBodyParseMethods = { "PUT", "POST", "OPTIONS", "PATCH" };
|
||||
private static readonly IDictionary<string, bool> BodyAllowedForMethods = new Dictionary<string, bool>
|
||||
{
|
||||
{ "HEAD", false },
|
||||
{ "GET", false },
|
||||
{ "PUT", true },
|
||||
{ "POST", true },
|
||||
{ "DELETE", false },
|
||||
{ "TRACE", false },
|
||||
{ "OPTIONS", true },
|
||||
{ "CONNECT", false },
|
||||
{ "PATCH", true }
|
||||
};
|
||||
|
||||
private static readonly IStringMatcher[] MultipartContentTypesMatchers = {
|
||||
new WildcardMatcher("multipart/*", true)
|
||||
@@ -52,7 +65,19 @@ namespace WireMock.Util
|
||||
|
||||
public static bool ShouldParseBody([CanBeNull] string method)
|
||||
{
|
||||
return AllowedBodyParseMethods.Contains(method, StringComparer.OrdinalIgnoreCase);
|
||||
if (String.IsNullOrEmpty(method))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (BodyAllowedForMethods.TryGetValue(method.ToUpper(), out var allowed))
|
||||
{
|
||||
return allowed;
|
||||
}
|
||||
// If we don't have any knowledge of this method, we should assume that a body *may*
|
||||
// be present, so we should parse it if it is. Therefore, if a new method is added to
|
||||
// the HTTP Method Registry, we only really need to add it to BodyAllowedForMethods if
|
||||
// we want to make it clear that a body is *not* allowed.
|
||||
return true;
|
||||
}
|
||||
|
||||
public static BodyType DetectBodyTypeFromContentType([CanBeNull] string contentTypeValue)
|
||||
@@ -91,9 +116,19 @@ namespace WireMock.Util
|
||||
DetectedBodyTypeFromContentType = DetectBodyTypeFromContentType(contentType)
|
||||
};
|
||||
|
||||
// In case of MultiPart: never try to read as String but keep as-is
|
||||
// In case of MultiPart: check if the BodyAsBytes is a valid UTF8 or ASCII string, in that case read as String else keep as-is
|
||||
if (data.DetectedBodyTypeFromContentType == BodyType.MultiPart)
|
||||
{
|
||||
if (BytesEncodingUtils.TryGetEncoding(data.BodyAsBytes, out Encoding encoding) &&
|
||||
SupportedBodyAsStringEncodingForMultipart.Select(x => x.Equals(encoding)).Any())
|
||||
{
|
||||
data.BodyAsString = encoding.GetString(data.BodyAsBytes);
|
||||
data.Encoding = encoding;
|
||||
data.DetectedBodyType = BodyType.String;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
230
src/WireMock.Net/Util/BytesEncodingUtils.cs
Normal file
230
src/WireMock.Net/Util/BytesEncodingUtils.cs
Normal file
@@ -0,0 +1,230 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace WireMock.Util
|
||||
{
|
||||
/// <summary>
|
||||
/// Based on:
|
||||
/// http://utf8checker.codeplex.com
|
||||
/// https://github.com/0x53A/Mvvm/blob/master/src/Mvvm/src/Utf8Checker.cs
|
||||
///
|
||||
/// References:
|
||||
/// http://anubis.dkuug.dk/JTC1/SC2/WG2/docs/n1335
|
||||
/// http://www.cl.cam.ac.uk/~mgk25/ucs/ISO-10646-UTF-8.html
|
||||
/// http://www.unicode.org/versions/corrigendum1.html
|
||||
/// http://www.ietf.org/rfc/rfc2279.txt
|
||||
/// </summary>
|
||||
public static class BytesEncodingUtils
|
||||
{
|
||||
/// <summary>
|
||||
/// Tries the get the Encoding from an array of bytes.
|
||||
/// </summary>
|
||||
/// <param name="bytes">The bytes.</param>
|
||||
/// <param name="encoding">The output encoding.</param>
|
||||
public static bool TryGetEncoding(byte[] bytes, out Encoding encoding)
|
||||
{
|
||||
encoding = null;
|
||||
if (bytes.All(b => b < 80))
|
||||
{
|
||||
encoding = Encoding.ASCII;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (StartsWith(bytes, new byte[] { 0xff, 0xfe, 0x00, 0x00 }))
|
||||
{
|
||||
encoding = Encoding.UTF32;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (StartsWith(bytes, new byte[] { 0xfe, 0xff }))
|
||||
{
|
||||
encoding = Encoding.BigEndianUnicode;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (StartsWith(bytes, new byte[] { 0xff, 0xfe }))
|
||||
{
|
||||
encoding = Encoding.Unicode;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (StartsWith(bytes, new byte[] { 0xef, 0xbb, 0xbf }))
|
||||
{
|
||||
encoding = Encoding.UTF8;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (IsUtf8(bytes, bytes.Length))
|
||||
{
|
||||
encoding = new UTF8Encoding(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool StartsWith(IEnumerable<byte> data, IReadOnlyCollection<byte> other)
|
||||
{
|
||||
byte[] arraySelf = data.Take(other.Count).ToArray();
|
||||
return other.SequenceEqual(arraySelf);
|
||||
}
|
||||
|
||||
private static bool IsUtf8(IReadOnlyList<byte> buffer, int length)
|
||||
{
|
||||
int position = 0;
|
||||
int bytes = 0;
|
||||
while (position < length)
|
||||
{
|
||||
if (!IsValid(buffer, position, length, ref bytes))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
position += bytes;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#pragma warning disable S3776 // Cognitive Complexity of methods should not be too high
|
||||
private static bool IsValid(IReadOnlyList<byte> buffer, int position, int length, ref int bytes)
|
||||
{
|
||||
if (length > buffer.Count)
|
||||
{
|
||||
throw new ArgumentException("Invalid length");
|
||||
}
|
||||
|
||||
if (position > length - 1)
|
||||
{
|
||||
bytes = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
byte ch = buffer[position];
|
||||
if (ch <= 0x7F)
|
||||
{
|
||||
bytes = 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ch >= 0xc2 && ch <= 0xdf)
|
||||
{
|
||||
if (position >= length - 2)
|
||||
{
|
||||
bytes = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (buffer[position + 1] < 0x80 || buffer[position + 1] > 0xbf)
|
||||
{
|
||||
bytes = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
bytes = 2;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ch == 0xe0)
|
||||
{
|
||||
if (position >= length - 3)
|
||||
{
|
||||
bytes = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (buffer[position + 1] < 0xa0 || buffer[position + 1] > 0xbf ||
|
||||
buffer[position + 2] < 0x80 || buffer[position + 2] > 0xbf)
|
||||
{
|
||||
bytes = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
bytes = 3;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ch >= 0xe1 && ch <= 0xef)
|
||||
{
|
||||
if (position >= length - 3)
|
||||
{
|
||||
bytes = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (buffer[position + 1] < 0x80 || buffer[position + 1] > 0xbf ||
|
||||
buffer[position + 2] < 0x80 || buffer[position + 2] > 0xbf)
|
||||
{
|
||||
bytes = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
bytes = 3;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ch == 0xf0)
|
||||
{
|
||||
if (position >= length - 4)
|
||||
{
|
||||
bytes = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (buffer[position + 1] < 0x90 || buffer[position + 1] > 0xbf ||
|
||||
buffer[position + 2] < 0x80 || buffer[position + 2] > 0xbf ||
|
||||
buffer[position + 3] < 0x80 || buffer[position + 3] > 0xbf)
|
||||
{
|
||||
bytes = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
bytes = 4;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ch == 0xf4)
|
||||
{
|
||||
if (position >= length - 4)
|
||||
{
|
||||
bytes = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (buffer[position + 1] < 0x80 || buffer[position + 1] > 0x8f ||
|
||||
buffer[position + 2] < 0x80 || buffer[position + 2] > 0xbf ||
|
||||
buffer[position + 3] < 0x80 || buffer[position + 3] > 0xbf)
|
||||
{
|
||||
bytes = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
bytes = 4;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ch >= 0xf1 && ch <= 0xf3)
|
||||
{
|
||||
if (position >= length - 4)
|
||||
{
|
||||
bytes = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (buffer[position + 1] < 0x80 || buffer[position + 1] > 0xbf ||
|
||||
buffer[position + 2] < 0x80 || buffer[position + 2] > 0xbf ||
|
||||
buffer[position + 3] < 0x80 || buffer[position + 3] > 0xbf)
|
||||
{
|
||||
bytes = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
bytes = 4;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#pragma warning restore S3776 // Cognitive Complexity of methods should not be too high
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
using System.IO;
|
||||
using JetBrains.Annotations;
|
||||
using System.Threading;
|
||||
using JetBrains.Annotations;
|
||||
using WireMock.Handlers;
|
||||
using WireMock.Validation;
|
||||
|
||||
@@ -11,16 +10,19 @@ namespace WireMock.Util
|
||||
private const int NumberOfRetries = 3;
|
||||
private const int DelayOnRetry = 500;
|
||||
|
||||
public static string ReadAllTextWithRetryAndDelay([NotNull] IFileSystemHandler handler, [NotNull] string path)
|
||||
public static bool TryReadMappingFileWithRetryAndDelay([NotNull] IFileSystemHandler handler, [NotNull] string path, out string value)
|
||||
{
|
||||
Check.NotNull(handler, nameof(handler));
|
||||
Check.NotNullOrEmpty(path, nameof(path));
|
||||
|
||||
value = null;
|
||||
|
||||
for (int i = 1; i <= NumberOfRetries; ++i)
|
||||
{
|
||||
try
|
||||
{
|
||||
return handler.ReadMappingFile(path);
|
||||
value = handler.ReadMappingFile(path);
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
@@ -28,7 +30,7 @@ namespace WireMock.Util
|
||||
}
|
||||
}
|
||||
|
||||
throw new IOException();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
41
src/WireMock.Net/Util/QueryStringParser.cs
Normal file
41
src/WireMock.Net/Util/QueryStringParser.cs
Normal file
@@ -0,0 +1,41 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace WireMock.Util
|
||||
{
|
||||
/// <summary>
|
||||
/// Based on https://stackoverflow.com/questions/659887/get-url-parameters-from-a-string-in-net
|
||||
/// </summary>
|
||||
internal static class QueryStringParser
|
||||
{
|
||||
public static IDictionary<string, WireMockList<string>> Parse(string queryString)
|
||||
{
|
||||
if (string.IsNullOrEmpty(queryString))
|
||||
{
|
||||
return new Dictionary<string, WireMockList<string>>();
|
||||
}
|
||||
|
||||
string[] JoinParts(string[] parts)
|
||||
{
|
||||
if (parts.Length > 2)
|
||||
{
|
||||
return new[] { string.Join("=", parts, 1, parts.Length - 1) };
|
||||
}
|
||||
|
||||
if (parts.Length > 1)
|
||||
{
|
||||
return parts[1].Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries); // support "?key=1,2"
|
||||
}
|
||||
|
||||
return new string[0];
|
||||
}
|
||||
|
||||
return queryString.TrimStart('?')
|
||||
.Split(new[] { '&', ';' }, StringSplitOptions.RemoveEmptyEntries) // Support "?key=value;key=anotherValue" and "?key=value&key=anotherValue"
|
||||
.Select(parameter => parameter.Split(new[] { '=' }, StringSplitOptions.RemoveEmptyEntries))
|
||||
.GroupBy(parts => parts[0], JoinParts)
|
||||
.ToDictionary(grouping => grouping.Key, grouping => new WireMockList<string>(grouping.SelectMany(x => x)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,10 @@
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
|
||||
<CodeAnalysisRuleSet>WireMock.Net.ruleset</CodeAnalysisRuleSet>
|
||||
<SignAssembly>true</SignAssembly>
|
||||
<AssemblyOriginatorKeyFile>WireMock.Net.snk</AssemblyOriginatorKeyFile>
|
||||
<!--<DelaySign>true</DelaySign>-->
|
||||
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
|
||||
@@ -57,8 +61,9 @@
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.0.9" />
|
||||
<PackageReference Include="RandomDataGenerator.Net" Version="1.0.7" />
|
||||
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.0.12" />
|
||||
<PackageReference Include="RandomDataGenerator.Net" Version="1.0.8" />
|
||||
<PackageReference Include="JmesPath.Net" Version="1.0.125" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition=" '$(TargetFramework)' == 'net451' ">
|
||||
|
||||
BIN
src/WireMock.Net/WireMock.Net.snk
Normal file
BIN
src/WireMock.Net/WireMock.Net.snk
Normal file
Binary file not shown.
215
test/WireMock.Net.Tests/FLuentMockServerTests.AdminFiles.cs
Normal file
215
test/WireMock.Net.Tests/FLuentMockServerTests.AdminFiles.cs
Normal file
@@ -0,0 +1,215 @@
|
||||
using Moq;
|
||||
using NFluent;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using WireMock.Handlers;
|
||||
using WireMock.Server;
|
||||
using WireMock.Settings;
|
||||
using Xunit;
|
||||
|
||||
namespace WireMock.Net.Tests
|
||||
{
|
||||
public class FluentMockServerAdminFilesTests
|
||||
{
|
||||
private readonly HttpClient _client = new HttpClient();
|
||||
|
||||
[Fact]
|
||||
public async Task FluentMockServer_Admin_Files_Post_Ascii()
|
||||
{
|
||||
// Arrange
|
||||
var filesystemHandlerMock = new Mock<IFileSystemHandler>(MockBehavior.Strict);
|
||||
filesystemHandlerMock.Setup(fs => fs.GetMappingFolder()).Returns("__admin/mappings");
|
||||
filesystemHandlerMock.Setup(fs => fs.FolderExists(It.IsAny<string>())).Returns(true);
|
||||
filesystemHandlerMock.Setup(fs => fs.WriteFile(It.IsAny<string>(), It.IsAny<byte[]>()));
|
||||
|
||||
var server = FluentMockServer.Start(new FluentMockServerSettings
|
||||
{
|
||||
UseSSL = false,
|
||||
StartAdminInterface = true,
|
||||
FileSystemHandler = filesystemHandlerMock.Object
|
||||
});
|
||||
|
||||
var multipartFormDataContent = new MultipartFormDataContent();
|
||||
multipartFormDataContent.Headers.ContentType = MediaTypeHeaderValue.Parse("multipart/form-data");
|
||||
multipartFormDataContent.Add(new StreamContent(new MemoryStream(Encoding.ASCII.GetBytes("Here's a string."))));
|
||||
|
||||
// Act
|
||||
var httpResponseMessage = await _client.PostAsync("http://localhost:" + server.Ports[0] + "/__admin/files/filename.txt", multipartFormDataContent);
|
||||
|
||||
// Assert
|
||||
Check.That(httpResponseMessage.StatusCode).Equals(HttpStatusCode.OK);
|
||||
Check.That(server.LogEntries.Count().Equals(1));
|
||||
|
||||
// Verify
|
||||
filesystemHandlerMock.Verify(fs => fs.GetMappingFolder(), Times.Once);
|
||||
filesystemHandlerMock.Verify(fs => fs.FolderExists(It.IsAny<string>()), Times.Once);
|
||||
filesystemHandlerMock.Verify(fs => fs.WriteFile(It.Is<string>(p => p == "filename.txt"), It.IsAny<byte[]>()), Times.Once);
|
||||
filesystemHandlerMock.VerifyNoOtherCalls();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task FluentMockServer_Admin_Files_Post_MappingFolderDoesNotExistsButWillBeCreated()
|
||||
{
|
||||
// Arrange
|
||||
var filesystemHandlerMock = new Mock<IFileSystemHandler>(MockBehavior.Strict);
|
||||
filesystemHandlerMock.Setup(fs => fs.GetMappingFolder()).Returns("x");
|
||||
filesystemHandlerMock.Setup(fs => fs.CreateFolder(It.IsAny<string>()));
|
||||
filesystemHandlerMock.Setup(fs => fs.FolderExists(It.IsAny<string>())).Returns(false);
|
||||
filesystemHandlerMock.Setup(fs => fs.WriteFile(It.IsAny<string>(), It.IsAny<byte[]>()));
|
||||
|
||||
var server = FluentMockServer.Start(new FluentMockServerSettings
|
||||
{
|
||||
UseSSL = false,
|
||||
StartAdminInterface = true,
|
||||
FileSystemHandler = filesystemHandlerMock.Object
|
||||
});
|
||||
|
||||
var multipartFormDataContent = new MultipartFormDataContent();
|
||||
multipartFormDataContent.Headers.ContentType = MediaTypeHeaderValue.Parse("multipart/form-data");
|
||||
multipartFormDataContent.Add(new StreamContent(new MemoryStream(Encoding.ASCII.GetBytes("Here's a string."))));
|
||||
|
||||
// Act
|
||||
var httpResponseMessage = await _client.PostAsync("http://localhost:" + server.Ports[0] + "/__admin/files/filename.txt", multipartFormDataContent);
|
||||
|
||||
// Assert
|
||||
Check.That(httpResponseMessage.StatusCode).Equals(HttpStatusCode.OK);
|
||||
|
||||
// Verify
|
||||
filesystemHandlerMock.Verify(fs => fs.GetMappingFolder(), Times.Once);
|
||||
filesystemHandlerMock.Verify(fs => fs.FolderExists(It.IsAny<string>()), Times.Once);
|
||||
filesystemHandlerMock.Verify(fs => fs.CreateFolder(It.Is<string>(p => p == "x")), Times.Once);
|
||||
filesystemHandlerMock.Verify(fs => fs.WriteFile(It.Is<string>(p => p == "filename.txt"), It.IsAny<byte[]>()), Times.Once);
|
||||
filesystemHandlerMock.VerifyNoOtherCalls();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task FluentMockServer_Admin_Files_GetAscii()
|
||||
{
|
||||
// Arrange
|
||||
var filesystemHandlerMock = new Mock<IFileSystemHandler>(MockBehavior.Strict);
|
||||
filesystemHandlerMock.Setup(fs => fs.FileExists(It.IsAny<string>())).Returns(true);
|
||||
filesystemHandlerMock.Setup(fs => fs.ReadFile(It.IsAny<string>())).Returns(Encoding.ASCII.GetBytes("Here's a string."));
|
||||
|
||||
var server = FluentMockServer.Start(new FluentMockServerSettings
|
||||
{
|
||||
UseSSL = false,
|
||||
StartAdminInterface = true,
|
||||
FileSystemHandler = filesystemHandlerMock.Object
|
||||
});
|
||||
|
||||
var multipartFormDataContent = new MultipartFormDataContent();
|
||||
multipartFormDataContent.Headers.ContentType = MediaTypeHeaderValue.Parse("multipart/form-data");
|
||||
multipartFormDataContent.Add(new StreamContent(new MemoryStream()));
|
||||
|
||||
// Act
|
||||
var httpResponseMessageGet = await _client.GetAsync("http://localhost:" + server.Ports[0] + "/__admin/files/filename.txt");
|
||||
|
||||
// Assert
|
||||
Check.That(httpResponseMessageGet.StatusCode).Equals(HttpStatusCode.OK);
|
||||
|
||||
Check.That(httpResponseMessageGet.Content.ReadAsStringAsync().Result).Equals("Here's a string.");
|
||||
|
||||
Check.That(server.LogEntries.Count().Equals(2));
|
||||
|
||||
// Verify
|
||||
filesystemHandlerMock.Verify(fs => fs.ReadFile(It.Is<string>(p => p == "filename.txt")), Times.Once);
|
||||
filesystemHandlerMock.Verify(fs => fs.FileExists(It.Is<string>(p => p == "filename.txt")), Times.Once);
|
||||
filesystemHandlerMock.VerifyNoOtherCalls();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task FluentMockServer_Admin_Files_GetUTF16()
|
||||
{
|
||||
// Arrange
|
||||
byte[] symbol = Encoding.UTF32.GetBytes(char.ConvertFromUtf32(0x1D161));
|
||||
var filesystemHandlerMock = new Mock<IFileSystemHandler>(MockBehavior.Strict);
|
||||
filesystemHandlerMock.Setup(fs => fs.FileExists(It.IsAny<string>())).Returns(true);
|
||||
filesystemHandlerMock.Setup(fs => fs.ReadFile(It.IsAny<string>())).Returns(symbol);
|
||||
|
||||
var server = FluentMockServer.Start(new FluentMockServerSettings
|
||||
{
|
||||
UseSSL = false,
|
||||
StartAdminInterface = true,
|
||||
FileSystemHandler = filesystemHandlerMock.Object
|
||||
});
|
||||
|
||||
var multipartFormDataContent = new MultipartFormDataContent();
|
||||
multipartFormDataContent.Headers.ContentType = MediaTypeHeaderValue.Parse("multipart/form-data");
|
||||
multipartFormDataContent.Add(new StreamContent(new MemoryStream()));
|
||||
|
||||
// Act
|
||||
var httpResponseMessageGet = await _client.GetAsync("http://localhost:" + server.Ports[0] + "/__admin/files/filename.bin");
|
||||
|
||||
// Assert
|
||||
Check.That(httpResponseMessageGet.StatusCode).Equals(HttpStatusCode.OK);
|
||||
Check.That(httpResponseMessageGet.Content.ReadAsByteArrayAsync().Result).Equals(symbol);
|
||||
Check.That(server.LogEntries.Count().Equals(2));
|
||||
|
||||
// Verify
|
||||
filesystemHandlerMock.Verify(fs => fs.ReadFile(It.Is<string>(p => p == "filename.bin")), Times.Once);
|
||||
filesystemHandlerMock.Verify(fs => fs.FileExists(It.Is<string>(p => p == "filename.bin")), Times.Once);
|
||||
filesystemHandlerMock.VerifyNoOtherCalls();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task FluentMockServer_Admin_Files_Head()
|
||||
{
|
||||
// Arrange
|
||||
var filesystemHandlerMock = new Mock<IFileSystemHandler>(MockBehavior.Strict);
|
||||
filesystemHandlerMock.Setup(fs => fs.FileExists(It.IsAny<string>())).Returns(true);
|
||||
|
||||
var server = FluentMockServer.Start(new FluentMockServerSettings
|
||||
{
|
||||
UseSSL = false,
|
||||
StartAdminInterface = true,
|
||||
FileSystemHandler = filesystemHandlerMock.Object
|
||||
});
|
||||
|
||||
// Act
|
||||
var requestUri = "http://localhost:" + server.Ports[0] + "/__admin/files/filename.txt";
|
||||
var httpRequestMessage = new HttpRequestMessage(HttpMethod.Head, requestUri);
|
||||
var httpResponseMessage = await _client.SendAsync(httpRequestMessage);
|
||||
|
||||
// Assert
|
||||
Check.That(httpResponseMessage.StatusCode).Equals(HttpStatusCode.NoContent);
|
||||
Check.That(server.LogEntries.Count().Equals(1));
|
||||
|
||||
// Verify
|
||||
filesystemHandlerMock.Verify(fs => fs.FileExists(It.IsAny<string>()), Times.Once);
|
||||
filesystemHandlerMock.VerifyNoOtherCalls();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task FluentMockServer_Admin_Files_Head_FileDoesNotExistsReturns404()
|
||||
{
|
||||
// Arrange
|
||||
var filesystemHandlerMock = new Mock<IFileSystemHandler>(MockBehavior.Strict);
|
||||
filesystemHandlerMock.Setup(fs => fs.FileExists(It.IsAny<string>())).Returns(false);
|
||||
|
||||
var server = FluentMockServer.Start(new FluentMockServerSettings
|
||||
{
|
||||
UseSSL = false,
|
||||
StartAdminInterface = true,
|
||||
FileSystemHandler = filesystemHandlerMock.Object
|
||||
});
|
||||
|
||||
// Act
|
||||
var requestUri = "http://localhost:" + server.Ports[0] + "/__admin/files/filename.txt";
|
||||
var httpRequestMessage = new HttpRequestMessage(HttpMethod.Head, requestUri);
|
||||
var httpResponseMessage = await _client.SendAsync(httpRequestMessage);
|
||||
|
||||
// Assert
|
||||
Check.That(httpResponseMessage.StatusCode).Equals(HttpStatusCode.NotFound);
|
||||
Check.That(server.LogEntries.Count().Equals(1));
|
||||
|
||||
// Verify
|
||||
filesystemHandlerMock.Verify(fs => fs.FileExists(It.IsAny<string>()), Times.Once);
|
||||
filesystemHandlerMock.VerifyNoOtherCalls();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,15 @@
|
||||
using NFluent;
|
||||
using Moq;
|
||||
using NFluent;
|
||||
using RestEase;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using WireMock.Admin.Mappings;
|
||||
using WireMock.Admin.Settings;
|
||||
using WireMock.Client;
|
||||
using WireMock.Handlers;
|
||||
using WireMock.Logging;
|
||||
using WireMock.Server;
|
||||
using WireMock.Settings;
|
||||
@@ -232,6 +235,237 @@ namespace WireMock.Net.Tests
|
||||
Check.That(requestLogged.Request.Body).IsNotNull();
|
||||
Check.That(requestLogged.Request.Body).Contains("T000001");
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task IFluentMockServerAdmin_PostFileAsync_Ascii()
|
||||
{
|
||||
// Arrange
|
||||
var filesystemHandlerMock = new Mock<IFileSystemHandler>(MockBehavior.Strict);
|
||||
filesystemHandlerMock.Setup(fs => fs.GetMappingFolder()).Returns("__admin/mappings");
|
||||
filesystemHandlerMock.Setup(fs => fs.FolderExists(It.IsAny<string>())).Returns(true);
|
||||
filesystemHandlerMock.Setup(fs => fs.WriteFile(It.IsAny<string>(), It.IsAny<byte[]>()));
|
||||
|
||||
var server = FluentMockServer.Start(new FluentMockServerSettings
|
||||
{
|
||||
UseSSL = false,
|
||||
StartAdminInterface = true,
|
||||
FileSystemHandler = filesystemHandlerMock.Object
|
||||
});
|
||||
|
||||
var api = RestClient.For<IFluentMockServerAdmin>(server.Urls[0]);
|
||||
|
||||
// Act
|
||||
var request = await api.PostFileAsync("filename.txt", "abc");
|
||||
|
||||
// Assert
|
||||
Check.That(request.Guid).IsNull();
|
||||
Check.That(request.Status).Contains("File");
|
||||
|
||||
// Verify
|
||||
filesystemHandlerMock.Verify(fs => fs.GetMappingFolder(), Times.Once);
|
||||
filesystemHandlerMock.Verify(fs => fs.FolderExists(It.IsAny<string>()), Times.Once);
|
||||
filesystemHandlerMock.Verify(fs => fs.WriteFile(It.Is<string>(p => p == "filename.txt"), It.IsAny<byte[]>()), Times.Once);
|
||||
filesystemHandlerMock.VerifyNoOtherCalls();
|
||||
|
||||
server.Stop();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task IFluentMockServerAdmin_PutFileAsync_Ascii()
|
||||
{
|
||||
// Arrange
|
||||
var filesystemHandlerMock = new Mock<IFileSystemHandler>(MockBehavior.Strict);
|
||||
filesystemHandlerMock.Setup(fs => fs.FileExists(It.IsAny<string>())).Returns(true);
|
||||
filesystemHandlerMock.Setup(fs => fs.WriteFile(It.IsAny<string>(), It.IsAny<byte[]>()));
|
||||
|
||||
var server = FluentMockServer.Start(new FluentMockServerSettings
|
||||
{
|
||||
UseSSL = false,
|
||||
StartAdminInterface = true,
|
||||
FileSystemHandler = filesystemHandlerMock.Object
|
||||
});
|
||||
|
||||
var api = RestClient.For<IFluentMockServerAdmin>(server.Urls[0]);
|
||||
|
||||
// Act
|
||||
var request = await api.PutFileAsync("filename.txt", "abc-abc");
|
||||
|
||||
// Assert
|
||||
Check.That(request.Guid).IsNull();
|
||||
Check.That(request.Status).Contains("File");
|
||||
|
||||
// Verify
|
||||
filesystemHandlerMock.Verify(fs => fs.WriteFile(It.Is<string>(p => p == "filename.txt"), It.IsAny<byte[]>()), Times.Once);
|
||||
filesystemHandlerMock.Verify(fs => fs.FileExists(It.Is<string>(p => p == "filename.txt")), Times.Once);
|
||||
filesystemHandlerMock.VerifyNoOtherCalls();
|
||||
|
||||
server.Stop();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IFluentMockServerAdmin_PutFileAsync_NotFound()
|
||||
{
|
||||
// Arrange
|
||||
var filesystemHandlerMock = new Mock<IFileSystemHandler>(MockBehavior.Strict);
|
||||
filesystemHandlerMock.Setup(fs => fs.FileExists(It.IsAny<string>())).Returns(false);
|
||||
|
||||
var server = FluentMockServer.Start(new FluentMockServerSettings
|
||||
{
|
||||
UseSSL = false,
|
||||
StartAdminInterface = true,
|
||||
FileSystemHandler = filesystemHandlerMock.Object
|
||||
});
|
||||
|
||||
var api = RestClient.For<IFluentMockServerAdmin>(server.Urls[0]);
|
||||
|
||||
// Act and Assert
|
||||
Check.ThatAsyncCode(() => api.PutFileAsync("filename.txt", "xxx")).Throws<ApiException>();
|
||||
|
||||
// Verify
|
||||
filesystemHandlerMock.Verify(fs => fs.FileExists(It.Is<string>(p => p == "filename.txt")), Times.Once);
|
||||
filesystemHandlerMock.VerifyNoOtherCalls();
|
||||
|
||||
server.Stop();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IFluentMockServerAdmin_GetFileAsync_NotFound()
|
||||
{
|
||||
// Arrange
|
||||
var filesystemHandlerMock = new Mock<IFileSystemHandler>(MockBehavior.Strict);
|
||||
filesystemHandlerMock.Setup(fs => fs.FileExists(It.IsAny<string>())).Returns(false);
|
||||
filesystemHandlerMock.Setup(fs => fs.ReadFile(It.IsAny<string>())).Returns(Encoding.ASCII.GetBytes("Here's a string."));
|
||||
|
||||
var server = FluentMockServer.Start(new FluentMockServerSettings
|
||||
{
|
||||
UseSSL = false,
|
||||
StartAdminInterface = true,
|
||||
FileSystemHandler = filesystemHandlerMock.Object
|
||||
});
|
||||
|
||||
var api = RestClient.For<IFluentMockServerAdmin>(server.Urls[0]);
|
||||
|
||||
// Act and Assert
|
||||
Check.ThatAsyncCode(() => api.GetFileAsync("filename.txt")).Throws<ApiException>();
|
||||
|
||||
// Verify
|
||||
filesystemHandlerMock.Verify(fs => fs.FileExists(It.Is<string>(p => p == "filename.txt")), Times.Once);
|
||||
filesystemHandlerMock.VerifyNoOtherCalls();
|
||||
|
||||
server.Stop();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task IFluentMockServerAdmin_GetFileAsync_Found()
|
||||
{
|
||||
// Arrange
|
||||
string data = "Here's a string.";
|
||||
var filesystemHandlerMock = new Mock<IFileSystemHandler>(MockBehavior.Strict);
|
||||
filesystemHandlerMock.Setup(fs => fs.FileExists(It.IsAny<string>())).Returns(true);
|
||||
filesystemHandlerMock.Setup(fs => fs.ReadFile(It.IsAny<string>())).Returns(Encoding.ASCII.GetBytes(data));
|
||||
|
||||
var server = FluentMockServer.Start(new FluentMockServerSettings
|
||||
{
|
||||
UseSSL = false,
|
||||
StartAdminInterface = true,
|
||||
FileSystemHandler = filesystemHandlerMock.Object
|
||||
});
|
||||
|
||||
var api = RestClient.For<IFluentMockServerAdmin>(server.Urls[0]);
|
||||
|
||||
// Act
|
||||
string file = await api.GetFileAsync("filename.txt");
|
||||
|
||||
// Assert
|
||||
Check.That(file).Equals(data);
|
||||
|
||||
// Verify
|
||||
filesystemHandlerMock.Verify(fs => fs.FileExists(It.Is<string>(p => p == "filename.txt")), Times.Once);
|
||||
filesystemHandlerMock.Verify(fs => fs.ReadFile(It.Is<string>(p => p == "filename.txt")), Times.Once);
|
||||
filesystemHandlerMock.VerifyNoOtherCalls();
|
||||
|
||||
server.Stop();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task IFluentMockServerAdmin_DeleteFileAsync_Ok()
|
||||
{
|
||||
// Arrange
|
||||
var filesystemHandlerMock = new Mock<IFileSystemHandler>(MockBehavior.Strict);
|
||||
filesystemHandlerMock.Setup(fs => fs.FileExists(It.IsAny<string>())).Returns(true);
|
||||
filesystemHandlerMock.Setup(fs => fs.DeleteFile(It.IsAny<string>()));
|
||||
|
||||
var server = FluentMockServer.Start(new FluentMockServerSettings
|
||||
{
|
||||
UseSSL = false,
|
||||
StartAdminInterface = true,
|
||||
FileSystemHandler = filesystemHandlerMock.Object
|
||||
});
|
||||
|
||||
var api = RestClient.For<IFluentMockServerAdmin>(server.Urls[0]);
|
||||
|
||||
// Act
|
||||
await api.DeleteFileAsync("filename.txt");
|
||||
|
||||
// Verify
|
||||
filesystemHandlerMock.Verify(fs => fs.FileExists(It.Is<string>(p => p == "filename.txt")), Times.Once);
|
||||
filesystemHandlerMock.Verify(fs => fs.DeleteFile(It.Is<string>(p => p == "filename.txt")), Times.Once);
|
||||
filesystemHandlerMock.VerifyNoOtherCalls();
|
||||
|
||||
server.Stop();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IFluentMockServerAdmin_DeleteFileAsync_NotFound()
|
||||
{
|
||||
// Arrange
|
||||
var filesystemHandlerMock = new Mock<IFileSystemHandler>(MockBehavior.Strict);
|
||||
filesystemHandlerMock.Setup(fs => fs.FileExists(It.IsAny<string>())).Returns(false);
|
||||
filesystemHandlerMock.Setup(fs => fs.DeleteFile(It.IsAny<string>()));
|
||||
|
||||
var server = FluentMockServer.Start(new FluentMockServerSettings
|
||||
{
|
||||
UseSSL = false,
|
||||
StartAdminInterface = true,
|
||||
FileSystemHandler = filesystemHandlerMock.Object
|
||||
});
|
||||
|
||||
var api = RestClient.For<IFluentMockServerAdmin>(server.Urls[0]);
|
||||
|
||||
// Act and Assert
|
||||
Check.ThatAsyncCode(() => api.DeleteFileAsync("filename.txt")).Throws<ApiException>();
|
||||
|
||||
// Verify
|
||||
filesystemHandlerMock.Verify(fs => fs.FileExists(It.Is<string>(p => p == "filename.txt")), Times.Once);
|
||||
filesystemHandlerMock.VerifyNoOtherCalls();
|
||||
|
||||
server.Stop();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IFluentMockServerAdmin_FileExistsAsync_NotFound()
|
||||
{
|
||||
// Arrange
|
||||
var filesystemHandlerMock = new Mock<IFileSystemHandler>(MockBehavior.Strict);
|
||||
filesystemHandlerMock.Setup(fs => fs.FileExists(It.IsAny<string>())).Returns(false);
|
||||
|
||||
var server = FluentMockServer.Start(new FluentMockServerSettings
|
||||
{
|
||||
UseSSL = false,
|
||||
StartAdminInterface = true,
|
||||
FileSystemHandler = filesystemHandlerMock.Object
|
||||
});
|
||||
|
||||
var api = RestClient.For<IFluentMockServerAdmin>(server.Urls[0]);
|
||||
|
||||
// Act and Assert
|
||||
Check.ThatAsyncCode(() => api.FileExistsAsync("filename.txt")).Throws<ApiException>();
|
||||
|
||||
// Verify
|
||||
filesystemHandlerMock.Verify(fs => fs.FileExists(It.Is<string>(p => p == "filename.txt")), Times.Once);
|
||||
filesystemHandlerMock.VerifyNoOtherCalls();
|
||||
|
||||
server.Stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
using System;
|
||||
using Moq;
|
||||
using Newtonsoft.Json;
|
||||
using NFluent;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Moq;
|
||||
using Newtonsoft.Json;
|
||||
using NFluent;
|
||||
using WireMock.Handlers;
|
||||
using WireMock.Logging;
|
||||
using WireMock.RequestBuilders;
|
||||
@@ -47,12 +47,14 @@ namespace WireMock.Net.Tests
|
||||
server.ReadStaticMappings(folder);
|
||||
|
||||
Check.That(server.Mappings).HasSize(5);
|
||||
Check.That(server.MappingModels).HasSize(5);
|
||||
|
||||
// Act
|
||||
server.ResetMappings();
|
||||
|
||||
// Assert
|
||||
Check.That(server.Mappings).HasSize(0);
|
||||
Check.That(server.MappingModels).HasSize(0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -375,5 +377,32 @@ namespace WireMock.Net.Tests
|
||||
fileMock.Verify(f => f.GetMappingFolder(), Times.Once);
|
||||
fileMock.Verify(f => f.FolderExists(It.IsAny<string>()), Times.Once);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FluentMockServer_Admin_AddMappingsAndSaveToFile()
|
||||
{
|
||||
// Assign
|
||||
string guid = "791a3f31-6946-aaaa-8e6f-0237c7442222";
|
||||
var staticMappingHandlerMock = new Mock<IFileSystemHandler>();
|
||||
staticMappingHandlerMock.Setup(m => m.GetMappingFolder()).Returns("folder");
|
||||
staticMappingHandlerMock.Setup(m => m.FolderExists(It.IsAny<string>())).Returns(true);
|
||||
staticMappingHandlerMock.Setup(m => m.WriteMappingFile(It.IsAny<string>(), It.IsAny<string>()));
|
||||
|
||||
var server = FluentMockServer.Start(new FluentMockServerSettings
|
||||
{
|
||||
FileSystemHandler = staticMappingHandlerMock.Object
|
||||
});
|
||||
|
||||
// Act
|
||||
server
|
||||
.Given(Request.Create().WithPath($"/foo_{Guid.NewGuid()}"), true)
|
||||
.WithGuid(guid)
|
||||
.RespondWith(Response.Create().WithBody("post and save test"));
|
||||
|
||||
// Assert and Verify
|
||||
staticMappingHandlerMock.Verify(m => m.GetMappingFolder(), Times.Once);
|
||||
staticMappingHandlerMock.Verify(m => m.FolderExists("folder"), Times.Once);
|
||||
staticMappingHandlerMock.Verify(m => m.WriteMappingFile(Path.Combine("folder", guid + ".json"), It.IsAny<string>()), Times.Once);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -290,6 +290,36 @@ namespace WireMock.Net.Tests
|
||||
Check.That(response.Content.Headers.GetValues("Content-Type")).ContainsExactly("application/json; charset=utf-8");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task FluentMockServer_Proxy_Should_set_Body_in_multipart_proxied_response()
|
||||
{
|
||||
// Assign
|
||||
string path = $"/prx_{Guid.NewGuid().ToString()}";
|
||||
var serverForProxyForwarding = FluentMockServer.Start();
|
||||
serverForProxyForwarding
|
||||
.Given(Request.Create().WithPath(path))
|
||||
.RespondWith(Response.Create()
|
||||
.WithBodyAsJson(new { i = 42 })
|
||||
);
|
||||
|
||||
var server = FluentMockServer.Start();
|
||||
server
|
||||
.Given(Request.Create().WithPath(path))
|
||||
.RespondWith(Response.Create().WithProxy(serverForProxyForwarding.Urls[0]));
|
||||
|
||||
// Act
|
||||
var uri = new Uri($"{server.Urls[0]}{path}");
|
||||
var form = new MultipartFormDataContent
|
||||
{
|
||||
{ new StringContent("data"), "test", "test.txt" }
|
||||
};
|
||||
var response = await new HttpClient().PostAsync(uri, form);
|
||||
|
||||
// Assert
|
||||
string content = await response.Content.ReadAsStringAsync();
|
||||
Check.That(content).IsEqualTo("{\"i\":42}");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task FluentMockServer_Proxy_Should_Not_overrule_AdminMappings()
|
||||
{
|
||||
|
||||
@@ -62,7 +62,7 @@ namespace WireMock.Net.Tests
|
||||
|
||||
// Assert
|
||||
var mappings = server.Mappings;
|
||||
Check.That(mappings.Count()).IsEqualTo(19);
|
||||
Check.That(mappings.Count()).IsEqualTo(24);
|
||||
Check.That(mappings.All(m => m.Priority == int.MinValue)).IsTrue();
|
||||
}
|
||||
|
||||
@@ -81,8 +81,8 @@ namespace WireMock.Net.Tests
|
||||
|
||||
// Assert
|
||||
var mappings = server.Mappings;
|
||||
Check.That(mappings.Count()).IsEqualTo(20);
|
||||
Check.That(mappings.Count(m => m.Priority == int.MinValue)).IsEqualTo(19);
|
||||
Check.That(mappings.Count()).IsEqualTo(25);
|
||||
Check.That(mappings.Count(m => m.Priority == int.MinValue)).IsEqualTo(24);
|
||||
Check.That(mappings.Count(m => m.Priority == 1000)).IsEqualTo(1);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using NFluent;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using WireMock.RequestBuilders;
|
||||
@@ -172,5 +173,65 @@ namespace WireMock.Net.Tests
|
||||
Check.That(response.Headers.Contains("test")).IsTrue();
|
||||
Check.That(response.Headers.Contains("Transfer-Encoding")).IsFalse();
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("DELETE")]
|
||||
#if !NET452
|
||||
[InlineData("TRACE")]
|
||||
[InlineData("GET")]
|
||||
#endif
|
||||
public async Task FluentMockServer_Should_exclude_body_for_methods_where_body_is_definitely_disallowed(string method)
|
||||
{
|
||||
// Assign
|
||||
string content = "hello";
|
||||
var server = FluentMockServer.Start();
|
||||
|
||||
server
|
||||
.Given(Request.Create().WithBody(b => true))
|
||||
.AtPriority(0)
|
||||
.RespondWith(Response.Create().WithStatusCode(400));
|
||||
server
|
||||
.Given(Request.Create())
|
||||
.AtPriority(1)
|
||||
.RespondWith(Response.Create().WithStatusCode(200));
|
||||
|
||||
// Act
|
||||
var request = new HttpRequestMessage(new HttpMethod(method), "http://localhost:" + server.Ports[0] + "/");
|
||||
request.Content = new StringContent(content);
|
||||
var response = await new HttpClient().SendAsync(request);
|
||||
|
||||
// Assert
|
||||
Check.That(response.StatusCode).Equals(HttpStatusCode.OK);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("POST")]
|
||||
[InlineData("PUT")]
|
||||
[InlineData("OPTIONS")]
|
||||
[InlineData("REPORT")]
|
||||
[InlineData("SOME-UNKNOWN-METHOD")] // default behavior for unknown methods is to allow a body (see BodyParser.ShouldParseBody)
|
||||
public async Task FluentMockServer_Should_not_exclude_body_for_supported_methods(string method)
|
||||
{
|
||||
// Assign
|
||||
string content = "hello";
|
||||
var server = FluentMockServer.Start();
|
||||
|
||||
server
|
||||
.Given(Request.Create().WithBody(content))
|
||||
.AtPriority(0)
|
||||
.RespondWith(Response.Create().WithStatusCode(200));
|
||||
server
|
||||
.Given(Request.Create())
|
||||
.AtPriority(1)
|
||||
.RespondWith(Response.Create().WithStatusCode(400));
|
||||
|
||||
// Act
|
||||
var request = new HttpRequestMessage(new HttpMethod(method), "http://localhost:" + server.Ports[0] + "/");
|
||||
request.Content = new StringContent(content);
|
||||
var response = await new HttpClient().SendAsync(request);
|
||||
|
||||
// Assert
|
||||
Check.That(response.StatusCode).Equals(HttpStatusCode.OK);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
using System;
|
||||
using NFluent;
|
||||
using System;
|
||||
using System.IO;
|
||||
using NFluent;
|
||||
using WireMock.Handlers;
|
||||
using Xunit;
|
||||
|
||||
@@ -21,24 +21,62 @@ namespace WireMock.Net.Tests.Handlers
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LocalFileSystemHandler_CreateFolder_Throws()
|
||||
public void LocalFileSystemHandler_CreateFolder_ThrowsArgumentNullException()
|
||||
{
|
||||
// Act
|
||||
Check.ThatCode(() => _sut.CreateFolder(null)).Throws<ArgumentNullException>();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LocalFileSystemHandler_WriteMappingFile_Throws()
|
||||
public void LocalFileSystemHandler_WriteMappingFile_ThrowsArgumentNullException()
|
||||
{
|
||||
// Act
|
||||
Check.ThatCode(() => _sut.WriteMappingFile(null, null)).Throws<ArgumentNullException>();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LocalFileSystemHandler_ReadResponseBodyAsFile_Throws()
|
||||
public void LocalFileSystemHandler_ReadResponseBodyAsFile_ThrowsArgumentNullException()
|
||||
{
|
||||
// Act
|
||||
Check.ThatCode(() => _sut.ReadResponseBodyAsFile(null)).Throws<ArgumentNullException>();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LocalFileSystemHandler_FileExists_ReturnsFalse()
|
||||
{
|
||||
// Act
|
||||
var result = _sut.FileExists("x.x");
|
||||
|
||||
// Assert
|
||||
Check.That(result).IsFalse();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LocalFileSystemHandler_FileExists_ThrowsArgumentNullException()
|
||||
{
|
||||
// Act
|
||||
Check.ThatCode(() => _sut.FileExists(null)).Throws<ArgumentNullException>();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LocalFileSystemHandler_ReadFile_ThrowsArgumentNullException()
|
||||
{
|
||||
// Act
|
||||
Check.ThatCode(() => _sut.ReadFile(null)).Throws<ArgumentNullException>();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LocalFileSystemHandler_WriteFile_ThrowsArgumentNullException()
|
||||
{
|
||||
// Act
|
||||
Check.ThatCode(() => _sut.WriteFile(null, null)).Throws<ArgumentNullException>();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LocalFileSystemHandler_DeleteFile_ThrowsArgumentNullException()
|
||||
{
|
||||
// Act
|
||||
Check.ThatCode(() => _sut.DeleteFile(null)).Throws<ArgumentNullException>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -33,7 +33,33 @@ namespace WireMock.Net.Tests.Matchers
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ExactMatcher_IsMatch_MultiplePatterns()
|
||||
public void ExactMatcher_IsMatch_WithSinglePattern_ReturnsMatch1_0()
|
||||
{
|
||||
// Assign
|
||||
var matcher = new ExactMatcher("x");
|
||||
|
||||
// Act
|
||||
double result = matcher.IsMatch("x");
|
||||
|
||||
// Assert
|
||||
Check.That(result).IsEqualTo(1.0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ExactMatcher_IsMatch_WithSinglePattern_ReturnsMatch0_0()
|
||||
{
|
||||
// Assign
|
||||
var matcher = new ExactMatcher("x");
|
||||
|
||||
// Act
|
||||
double result = matcher.IsMatch("y");
|
||||
|
||||
// Assert
|
||||
Check.That(result).IsEqualTo(0.0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ExactMatcher_IsMatch_WithMultiplePatterns_ReturnsMatch0_5()
|
||||
{
|
||||
// Assign
|
||||
var matcher = new ExactMatcher("x", "y");
|
||||
@@ -42,7 +68,7 @@ namespace WireMock.Net.Tests.Matchers
|
||||
double result = matcher.IsMatch("x");
|
||||
|
||||
// Assert
|
||||
Check.That(result).IsEqualTo(0.5d);
|
||||
Check.That(result).IsEqualTo(1.0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
||||
166
test/WireMock.Net.Tests/Matchers/JmesPathMatcherTests.cs
Normal file
166
test/WireMock.Net.Tests/Matchers/JmesPathMatcherTests.cs
Normal file
@@ -0,0 +1,166 @@
|
||||
using Newtonsoft.Json.Linq;
|
||||
using NFluent;
|
||||
using WireMock.Matchers;
|
||||
using Xunit;
|
||||
|
||||
namespace WireMock.Net.Tests.Matchers
|
||||
{
|
||||
public class JmesPathMatcherTests
|
||||
{
|
||||
[Fact]
|
||||
public void JmesPathMatcher_GetName()
|
||||
{
|
||||
// Assign
|
||||
var matcher = new JmesPathMatcher("X");
|
||||
|
||||
// Act
|
||||
string name = matcher.Name;
|
||||
|
||||
// Assert
|
||||
Check.That(name).Equals("JmesPathMatcher");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void JmesPathMatcher_GetPatterns()
|
||||
{
|
||||
// Assign
|
||||
var matcher = new JmesPathMatcher("X");
|
||||
|
||||
// Act
|
||||
string[] patterns = matcher.GetPatterns();
|
||||
|
||||
// Assert
|
||||
Check.That(patterns).ContainsExactly("X");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void JmesPathMatcher_IsMatch_ByteArray()
|
||||
{
|
||||
// Assign
|
||||
var bytes = new byte[0];
|
||||
var matcher = new JmesPathMatcher("");
|
||||
|
||||
// Act
|
||||
double match = matcher.IsMatch(bytes);
|
||||
|
||||
// Assert
|
||||
Check.That(match).IsEqualTo(0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void JmesPathMatcher_IsMatch_NullString()
|
||||
{
|
||||
// Assign
|
||||
string s = null;
|
||||
var matcher = new JmesPathMatcher("");
|
||||
|
||||
// Act
|
||||
double match = matcher.IsMatch(s);
|
||||
|
||||
// Assert
|
||||
Check.That(match).IsEqualTo(0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void JmesPathMatcher_IsMatch_NullObject()
|
||||
{
|
||||
// Assign
|
||||
object o = null;
|
||||
var matcher = new JmesPathMatcher("");
|
||||
|
||||
// Act
|
||||
double match = matcher.IsMatch(o);
|
||||
|
||||
// Assert
|
||||
Check.That(match).IsEqualTo(0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void JmesPathMatcher_IsMatch_String_Exception_Mismatch()
|
||||
{
|
||||
// Assign
|
||||
var matcher = new JmesPathMatcher("xxx");
|
||||
|
||||
// Act
|
||||
double match = matcher.IsMatch("");
|
||||
|
||||
// Assert
|
||||
Check.That(match).IsEqualTo(0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void JmesPathMatcher_IsMatch_Object_Exception_Mismatch()
|
||||
{
|
||||
// Assign
|
||||
var matcher = new JmesPathMatcher("");
|
||||
|
||||
// Act
|
||||
double match = matcher.IsMatch("x");
|
||||
|
||||
// Assert
|
||||
Check.That(match).IsEqualTo(0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void JmesPathMatcher_IsMatch_AnonymousObject()
|
||||
{
|
||||
// Assign
|
||||
var matcher = new JmesPathMatcher("things.name == 'RequiredThing'");
|
||||
|
||||
// Act
|
||||
double match = matcher.IsMatch(new { things = new { name = "RequiredThing" } });
|
||||
|
||||
// Assert
|
||||
Check.That(match).IsEqualTo(1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void JmesPathMatcher_IsMatch_JObject()
|
||||
{
|
||||
// Assign
|
||||
string[] patterns = { "things.x == 'RequiredThing'" };
|
||||
var matcher = new JmesPathMatcher(patterns);
|
||||
|
||||
// Act
|
||||
var sub = new JObject
|
||||
{
|
||||
{ "x", new JValue("RequiredThing") }
|
||||
};
|
||||
var jobject = new JObject
|
||||
{
|
||||
{ "Id", new JValue(1) },
|
||||
{ "things", sub }
|
||||
};
|
||||
double match = matcher.IsMatch(jobject);
|
||||
|
||||
// Assert
|
||||
Check.That(match).IsEqualTo(1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void JmesPathMatcher_IsMatch_JObject_Parsed()
|
||||
{
|
||||
// Assign
|
||||
var matcher = new JmesPathMatcher("things.x == 'RequiredThing'");
|
||||
|
||||
// Act
|
||||
double match = matcher.IsMatch(JObject.Parse("{ \"things\": { \"x\": \"RequiredThing\" } }"));
|
||||
|
||||
// Assert
|
||||
Check.That(match).IsEqualTo(1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void JmesPathMatcher_IsMatch_RejectOnMatch()
|
||||
{
|
||||
// Assign
|
||||
var matcher = new JmesPathMatcher(MatchBehaviour.RejectOnMatch, "things.x == 'RequiredThing'");
|
||||
|
||||
// Act
|
||||
double match = matcher.IsMatch(JObject.Parse("{ \"things\": { \"x\": \"RequiredThing\" } }"));
|
||||
|
||||
// Assert
|
||||
Check.That(match).IsEqualTo(0.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,7 @@ namespace WireMock.Net.Tests.RequestBuilders
|
||||
|
||||
// Assert 1
|
||||
var matchers = requestBuilder.GetPrivateFieldValue<IList<IRequestMatcher>>("_requestMatchers");
|
||||
Check.That(matchers.Count()).IsEqualTo(1);
|
||||
Check.That(matchers.Count).IsEqualTo(1);
|
||||
Check.That((matchers[0] as RequestMessageMethodMatcher).Methods).ContainsExactly("PATCH");
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace WireMock.Net.Tests.RequestBuilders
|
||||
|
||||
// Assert 1
|
||||
var matchers = requestBuilder.GetPrivateFieldValue<IList<IRequestMatcher>>("_requestMatchers");
|
||||
Check.That(matchers.Count()).IsEqualTo(1);
|
||||
Check.That(matchers.Count).IsEqualTo(1);
|
||||
Check.That(matchers[0]).IsInstanceOfType(typeof(RequestMessageMethodMatcher));
|
||||
|
||||
// Act
|
||||
@@ -36,7 +36,7 @@ namespace WireMock.Net.Tests.RequestBuilders
|
||||
|
||||
// Assert 2
|
||||
matchers = requestBuilder.GetPrivateFieldValue<IList<IRequestMatcher>>("_requestMatchers");
|
||||
Check.That(matchers.Count()).IsEqualTo(0);
|
||||
Check.That(matchers.Count).IsEqualTo(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Collections.Generic;
|
||||
using NFluent;
|
||||
using FluentAssertions;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using WireMock.Matchers;
|
||||
using WireMock.Matchers.Request;
|
||||
using WireMock.RequestBuilders;
|
||||
@@ -20,8 +21,24 @@ namespace WireMock.Net.Tests.RequestBuilders
|
||||
|
||||
// Assert
|
||||
var matchers = requestBuilder.GetPrivateFieldValue<IList<IRequestMatcher>>("_requestMatchers");
|
||||
Check.That(matchers.Count()).IsEqualTo(1);
|
||||
Check.That(((RequestMessageBodyMatcher) matchers[0]).Matcher).IsEqualTo(matcher);
|
||||
matchers.Should().HaveCount(1);
|
||||
((RequestMessageBodyMatcher)matchers[0]).Matchers.Should().Contain(matcher);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RequestBuilder_WithBody_IMatchers()
|
||||
{
|
||||
// Assign
|
||||
var matcher1 = new WildcardMatcher("x");
|
||||
var matcher2 = new WildcardMatcher("y");
|
||||
|
||||
// Act
|
||||
var requestBuilder = (Request)Request.Create().WithBody(new[] { matcher1, matcher2 }.Cast<IMatcher>().ToArray());
|
||||
|
||||
// Assert
|
||||
var matchers = requestBuilder.GetPrivateFieldValue<IList<IRequestMatcher>>("_requestMatchers");
|
||||
matchers.Should().HaveCount(1);
|
||||
((RequestMessageBodyMatcher)matchers[0]).Matchers.Should().Contain(new[] { matcher1, matcher2 });
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,7 @@ namespace WireMock.Net.Tests.RequestBuilders
|
||||
|
||||
// Assert
|
||||
var matchers = requestBuilder.GetPrivateFieldValue<IList<IRequestMatcher>>("_requestMatchers");
|
||||
Check.That(matchers.Count()).IsEqualTo(1);
|
||||
Check.That(matchers.Count).IsEqualTo(1);
|
||||
Check.That(matchers[0]).IsInstanceOfType(typeof(RequestMessageCookieMatcher));
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace WireMock.Net.Tests.RequestBuilders
|
||||
|
||||
// Assert
|
||||
var matchers = requestBuilder.GetPrivateFieldValue<IList<IRequestMatcher>>("_requestMatchers");
|
||||
Check.That(matchers.Count()).IsEqualTo(1);
|
||||
Check.That(matchers.Count).IsEqualTo(1);
|
||||
Check.That(matchers[0]).IsInstanceOfType(typeof(RequestMessageCookieMatcher));
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace WireMock.Net.Tests.RequestBuilders
|
||||
|
||||
// Assert
|
||||
var matchers = requestBuilder.GetPrivateFieldValue<IList<IRequestMatcher>>("_requestMatchers");
|
||||
Check.That(matchers.Count()).IsEqualTo(1);
|
||||
Check.That(matchers.Count).IsEqualTo(1);
|
||||
Check.That(matchers[0]).IsInstanceOfType(typeof(RequestMessageCookieMatcher));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace WireMock.Net.Tests.RequestBuilders
|
||||
|
||||
// Assert
|
||||
var matchers = requestBuilder.GetPrivateFieldValue<IList<IRequestMatcher>>("_requestMatchers");
|
||||
Check.That(matchers.Count()).IsEqualTo(1);
|
||||
Check.That(matchers.Count).IsEqualTo(1);
|
||||
Check.That(matchers[0]).IsInstanceOfType(typeof(RequestMessageHeaderMatcher));
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace WireMock.Net.Tests.RequestBuilders
|
||||
|
||||
// Assert
|
||||
var matchers = requestBuilder.GetPrivateFieldValue<IList<IRequestMatcher>>("_requestMatchers");
|
||||
Check.That(matchers.Count()).IsEqualTo(1);
|
||||
Check.That(matchers.Count).IsEqualTo(1);
|
||||
Check.That(matchers[0]).IsInstanceOfType(typeof(RequestMessageHeaderMatcher));
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace WireMock.Net.Tests.RequestBuilders
|
||||
|
||||
// Assert
|
||||
var matchers = requestBuilder.GetPrivateFieldValue<IList<IRequestMatcher>>("_requestMatchers");
|
||||
Check.That(matchers.Count()).IsEqualTo(1);
|
||||
Check.That(matchers.Count).IsEqualTo(1);
|
||||
Check.That(matchers[0]).IsInstanceOfType(typeof(RequestMessageHeaderMatcher));
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ namespace WireMock.Net.Tests.RequestBuilders
|
||||
|
||||
// Assert
|
||||
var matchers = requestBuilder.GetPrivateFieldValue<IList<IRequestMatcher>>("_requestMatchers");
|
||||
Check.That(matchers.Count()).IsEqualTo(1);
|
||||
Check.That(matchers.Count).IsEqualTo(1);
|
||||
Check.That(matchers[0]).IsInstanceOfType(typeof(RequestMessageHeaderMatcher));
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ namespace WireMock.Net.Tests.RequestBuilders
|
||||
|
||||
// Assert
|
||||
var matchers = requestBuilder.GetPrivateFieldValue<IList<IRequestMatcher>>("_requestMatchers");
|
||||
Check.That(matchers.Count()).IsEqualTo(1);
|
||||
Check.That(matchers.Count).IsEqualTo(1);
|
||||
Check.That(matchers[0]).IsInstanceOfType(typeof(RequestMessageHeaderMatcher));
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ namespace WireMock.Net.Tests.RequestBuilders
|
||||
|
||||
// Assert
|
||||
var matchers = requestBuilder.GetPrivateFieldValue<IList<IRequestMatcher>>("_requestMatchers");
|
||||
Check.That(matchers.Count()).IsEqualTo(1);
|
||||
Check.That(matchers.Count).IsEqualTo(1);
|
||||
Check.That(matchers[0]).IsInstanceOfType(typeof(RequestMessageHeaderMatcher));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace WireMock.Net.Tests.RequestBuilders
|
||||
|
||||
// Assert
|
||||
var matchers = requestBuilder.GetPrivateFieldValue<IList<IRequestMatcher>>("_requestMatchers");
|
||||
Check.That(matchers.Count()).IsEqualTo(1);
|
||||
Check.That(matchers.Count).IsEqualTo(1);
|
||||
Check.That(matchers[0]).IsInstanceOfType(typeof(RequestMessageParamMatcher));
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace WireMock.Net.Tests.RequestBuilders
|
||||
|
||||
// Assert
|
||||
var matchers = requestBuilder.GetPrivateFieldValue<IList<IRequestMatcher>>("_requestMatchers");
|
||||
Check.That(matchers.Count()).IsEqualTo(1);
|
||||
Check.That(matchers.Count).IsEqualTo(1);
|
||||
Check.That(matchers[0]).IsInstanceOfType(typeof(RequestMessageParamMatcher));
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace WireMock.Net.Tests.RequestBuilders
|
||||
|
||||
// Assert
|
||||
var matchers = requestBuilder.GetPrivateFieldValue<IList<IRequestMatcher>>("_requestMatchers");
|
||||
Check.That(matchers.Count()).IsEqualTo(1);
|
||||
Check.That(matchers.Count).IsEqualTo(1);
|
||||
Check.That(matchers[0]).IsInstanceOfType(typeof(RequestMessageParamMatcher));
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ namespace WireMock.Net.Tests.RequestBuilders
|
||||
|
||||
// Assert
|
||||
var matchers = requestBuilder.GetPrivateFieldValue<IList<IRequestMatcher>>("_requestMatchers");
|
||||
Check.That(matchers.Count()).IsEqualTo(1);
|
||||
Check.That(matchers.Count).IsEqualTo(1);
|
||||
Check.That(matchers[0]).IsInstanceOfType(typeof(RequestMessageParamMatcher));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace WireMock.Net.Tests.RequestBuilders
|
||||
|
||||
// Assert
|
||||
var matchers = requestBuilder.GetPrivateFieldValue<IList<IRequestMatcher>>("_requestMatchers");
|
||||
Check.That(matchers.Count()).IsEqualTo(1);
|
||||
Check.That(matchers.Count).IsEqualTo(1);
|
||||
Check.That(matchers[0]).IsInstanceOfType(typeof(RequestMessageUrlMatcher));
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace WireMock.Net.Tests.RequestBuilders
|
||||
|
||||
// Assert
|
||||
var matchers = requestBuilder.GetPrivateFieldValue<IList<IRequestMatcher>>("_requestMatchers");
|
||||
Check.That(matchers.Count()).IsEqualTo(1);
|
||||
Check.That(matchers.Count).IsEqualTo(1);
|
||||
Check.That(matchers[0]).IsInstanceOfType(typeof(RequestMessageUrlMatcher));
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace WireMock.Net.Tests.RequestBuilders
|
||||
|
||||
// Assert
|
||||
var matchers = requestBuilder.GetPrivateFieldValue<IList<IRequestMatcher>>("_requestMatchers");
|
||||
Check.That(matchers.Count()).IsEqualTo(1);
|
||||
Check.That(matchers.Count).IsEqualTo(1);
|
||||
Check.That(matchers[0]).IsInstanceOfType(typeof(RequestMessageUrlMatcher));
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ namespace WireMock.Net.Tests.RequestBuilders
|
||||
|
||||
// Assert
|
||||
var matchers = requestBuilder.GetPrivateFieldValue<IList<IRequestMatcher>>("_requestMatchers");
|
||||
Check.That(matchers.Count()).IsEqualTo(1);
|
||||
Check.That(matchers.Count).IsEqualTo(1);
|
||||
Check.That(matchers[0]).IsInstanceOfType(typeof(RequestMessageUrlMatcher));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Moq;
|
||||
using System.Linq;
|
||||
using Moq;
|
||||
using NFluent;
|
||||
using WireMock.Matchers;
|
||||
using WireMock.Matchers.Request;
|
||||
@@ -38,6 +39,39 @@ namespace WireMock.Net.Tests.RequestMatchers
|
||||
stringMatcherMock.Verify(m => m.IsMatch("b"), Times.Once);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RequestMessageBodyMatcher_GetMatchingScore_BodyAsString_IStringMatchers()
|
||||
{
|
||||
// Assign
|
||||
var body = new BodyData
|
||||
{
|
||||
BodyAsString = "b",
|
||||
DetectedBodyType = BodyType.String
|
||||
};
|
||||
var stringMatcherMock1 = new Mock<IStringMatcher>();
|
||||
stringMatcherMock1.Setup(m => m.IsMatch(It.IsAny<string>())).Returns(0.2d);
|
||||
var stringMatcherMock2 = new Mock<IStringMatcher>();
|
||||
stringMatcherMock2.Setup(m => m.IsMatch(It.IsAny<string>())).Returns(0.8d);
|
||||
var matchers = new[] { stringMatcherMock1.Object, stringMatcherMock2.Object };
|
||||
|
||||
var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1", body);
|
||||
|
||||
var matcher = new RequestMessageBodyMatcher(matchers.Cast<IMatcher>().ToArray());
|
||||
|
||||
// Act
|
||||
var result = new RequestMatchResult();
|
||||
double score = matcher.GetMatchingScore(requestMessage, result);
|
||||
|
||||
// Assert
|
||||
Check.That(score).IsEqualTo(0.8d);
|
||||
|
||||
// Verify
|
||||
stringMatcherMock1.Verify(m => m.GetPatterns(), Times.Never);
|
||||
stringMatcherMock1.Verify(m => m.IsMatch("b"), Times.Once);
|
||||
stringMatcherMock2.Verify(m => m.GetPatterns(), Times.Never);
|
||||
stringMatcherMock2.Verify(m => m.IsMatch("b"), Times.Once);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RequestMessageBodyMatcher_GetMatchingScore_BodyAsBytes_IStringMatcher()
|
||||
{
|
||||
|
||||
@@ -9,11 +9,11 @@ namespace WireMock.Net.Tests.RequestMatchers
|
||||
public class RequestMessageParamMatcherTests
|
||||
{
|
||||
[Fact]
|
||||
public void RequestMessageParamMatcher_GetMatchingScore_KeyWithValuesPresentInUrl_MatchExactOnStringValues()
|
||||
public void RequestMessageParamMatcher_GetMatchingScore_IgnoreCaseKeyWithValuesPresentInUrl_And_With1StringValues_Returns1_0()
|
||||
{
|
||||
// Assign
|
||||
var requestMessage = new RequestMessage(new UrlDetails("http://localhost?key=test1,test2"), "GET", "127.0.0.1");
|
||||
var matcher = new RequestMessageParamMatcher(MatchBehaviour.AcceptOnMatch, "key", new[] { "test1", "test2" });
|
||||
var requestMessage = new RequestMessage(new UrlDetails("http://localhost?key=test1"), "GET", "127.0.0.1");
|
||||
var matcher = new RequestMessageParamMatcher(MatchBehaviour.AcceptOnMatch, "KeY", true, new[] { "test1" });
|
||||
|
||||
// Act
|
||||
var result = new RequestMatchResult();
|
||||
@@ -24,11 +24,71 @@ namespace WireMock.Net.Tests.RequestMatchers
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RequestMessageParamMatcher_GetMatchingScore_KeyWithValuesPresentInUrl_MatchExactOnExactMatchers()
|
||||
public void RequestMessageParamMatcher_GetMatchingScore_KeyWith1ValuePresentInUrl_And_With2Strings_Returns0_5()
|
||||
{
|
||||
// Assign
|
||||
var requestMessage = new RequestMessage(new UrlDetails("http://localhost?key=test1"), "GET", "127.0.0.1");
|
||||
var matcher = new RequestMessageParamMatcher(MatchBehaviour.AcceptOnMatch, "key", false, new[] { "test1", "test2" });
|
||||
|
||||
// Act
|
||||
var result = new RequestMatchResult();
|
||||
double score = matcher.GetMatchingScore(requestMessage, result);
|
||||
|
||||
// Assert
|
||||
Check.That(score).IsEqualTo(0.5d);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RequestMessageParamMatcher_GetMatchingScore_KeyWith3ValuesPresentInUrl_And_With1ExactStringWith2Patterns_Returns0_66()
|
||||
{
|
||||
// Assign
|
||||
var requestMessage = new RequestMessage(new UrlDetails("http://localhost?key=test1,test2,test3"), "GET", "127.0.0.1");
|
||||
var matcher = new RequestMessageParamMatcher(MatchBehaviour.AcceptOnMatch, "key", false, new IStringMatcher[] { new ExactMatcher("test1", "test2") });
|
||||
|
||||
// Act
|
||||
var result = new RequestMatchResult();
|
||||
double score = matcher.GetMatchingScore(requestMessage, result);
|
||||
|
||||
// Assert
|
||||
Check.That(score).IsCloseTo(0.66d, 0.1d);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RequestMessageParamMatcher_GetMatchingScore_KeyWith2ValuesPresentInUrl_And_With1ExactStringWith3Patterns_Returns0_66()
|
||||
{
|
||||
// Assign
|
||||
var requestMessage = new RequestMessage(new UrlDetails("http://localhost?key=test1,test2"), "GET", "127.0.0.1");
|
||||
var matcher = new RequestMessageParamMatcher(MatchBehaviour.AcceptOnMatch, "key", new IStringMatcher[] { new ExactMatcher("test1"), new ExactMatcher("test2") });
|
||||
var matcher = new RequestMessageParamMatcher(MatchBehaviour.AcceptOnMatch, "key", false, new IStringMatcher[] { new ExactMatcher("test1", "test2", "test3") });
|
||||
|
||||
// Act
|
||||
var result = new RequestMatchResult();
|
||||
double score = matcher.GetMatchingScore(requestMessage, result);
|
||||
|
||||
// Assert
|
||||
Check.That(score).IsCloseTo(0.66d, 0.1d);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RequestMessageParamMatcher_GetMatchingScore_KeyWith2ValuesPresentInUrl_And_With2Strings_Returns1_0()
|
||||
{
|
||||
// Assign
|
||||
var requestMessage = new RequestMessage(new UrlDetails("http://localhost?key=test1,test2"), "GET", "127.0.0.1");
|
||||
var matcher = new RequestMessageParamMatcher(MatchBehaviour.AcceptOnMatch, "key", false, new[] { "test1", "test2" });
|
||||
|
||||
// Act
|
||||
var result = new RequestMatchResult();
|
||||
double score = matcher.GetMatchingScore(requestMessage, result);
|
||||
|
||||
// Assert
|
||||
Check.That(score).IsEqualTo(1.0d);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RequestMessageParamMatcher_GetMatchingScore_KeyWith2ValuesPresentInUrl_And_With2ExactStringMatchers_Returns1_0()
|
||||
{
|
||||
// Assign
|
||||
var requestMessage = new RequestMessage(new UrlDetails("http://localhost?key=test1,test2"), "GET", "127.0.0.1");
|
||||
var matcher = new RequestMessageParamMatcher(MatchBehaviour.AcceptOnMatch, "key", false, new IStringMatcher[] { new ExactMatcher("test1"), new ExactMatcher("test2") });
|
||||
|
||||
// Act
|
||||
var result = new RequestMatchResult();
|
||||
@@ -43,7 +103,7 @@ namespace WireMock.Net.Tests.RequestMatchers
|
||||
{
|
||||
// Assign
|
||||
var requestMessage = new RequestMessage(new UrlDetails("http://localhost?key=test0,test2"), "GET", "127.0.0.1");
|
||||
var matcher = new RequestMessageParamMatcher(MatchBehaviour.AcceptOnMatch, "key", new[] { "test1", "test2" });
|
||||
var matcher = new RequestMessageParamMatcher(MatchBehaviour.AcceptOnMatch, "key", false, new[] { "test1", "test2" });
|
||||
|
||||
// Act
|
||||
var result = new RequestMatchResult();
|
||||
@@ -58,7 +118,7 @@ namespace WireMock.Net.Tests.RequestMatchers
|
||||
{
|
||||
// Assign
|
||||
var requestMessage = new RequestMessage(new UrlDetails("http://localhost?key"), "GET", "127.0.0.1");
|
||||
var matcher = new RequestMessageParamMatcher(MatchBehaviour.AcceptOnMatch, "key", new[] { "test1", "test2" });
|
||||
var matcher = new RequestMessageParamMatcher(MatchBehaviour.AcceptOnMatch, "key", false, new[] { "test1", "test2" });
|
||||
|
||||
// Act
|
||||
var result = new RequestMatchResult();
|
||||
@@ -73,7 +133,7 @@ namespace WireMock.Net.Tests.RequestMatchers
|
||||
{
|
||||
// Assign
|
||||
var requestMessage = new RequestMessage(new UrlDetails("http://localhost?key"), "GET", "127.0.0.1");
|
||||
var matcher = new RequestMessageParamMatcher(MatchBehaviour.AcceptOnMatch, "key");
|
||||
var matcher = new RequestMessageParamMatcher(MatchBehaviour.AcceptOnMatch, "key", false);
|
||||
|
||||
// Act
|
||||
var result = new RequestMatchResult();
|
||||
@@ -88,7 +148,7 @@ namespace WireMock.Net.Tests.RequestMatchers
|
||||
{
|
||||
// Assign
|
||||
var requestMessage = new RequestMessage(new UrlDetails("http://localhost?key"), "GET", "127.0.0.1");
|
||||
var matcher = new RequestMessageParamMatcher(MatchBehaviour.AcceptOnMatch, "key", new string[] { });
|
||||
var matcher = new RequestMessageParamMatcher(MatchBehaviour.AcceptOnMatch, "key", false, new string[] { });
|
||||
|
||||
// Act
|
||||
var result = new RequestMatchResult();
|
||||
@@ -103,7 +163,7 @@ namespace WireMock.Net.Tests.RequestMatchers
|
||||
{
|
||||
// Assign
|
||||
var requestMessage = new RequestMessage(new UrlDetails("http://localhost?key=frank@contoso.com"), "GET", "127.0.0.1");
|
||||
var matcher = new RequestMessageParamMatcher(MatchBehaviour.AcceptOnMatch, "key");
|
||||
var matcher = new RequestMessageParamMatcher(MatchBehaviour.AcceptOnMatch, "key", false);
|
||||
|
||||
// Act
|
||||
var result = new RequestMatchResult();
|
||||
|
||||
@@ -39,6 +39,16 @@ namespace WireMock.Net.Tests
|
||||
Check.That(request.GetParameter("foo")).ContainsExactly("bar");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RequestMessage_ParseQuery_SingleKey_SingleValue_WithIgnoreCase()
|
||||
{
|
||||
// Assign
|
||||
var request = new RequestMessage(new UrlDetails("http://localhost?foo=bar"), "POST", ClientIp);
|
||||
|
||||
// Assert
|
||||
Check.That(request.GetParameter("FoO", true)).ContainsExactly("bar");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RequestMessage_ParseQuery_MultipleKeys_MultipleValues()
|
||||
{
|
||||
@@ -50,6 +60,18 @@ namespace WireMock.Net.Tests
|
||||
Check.That(request.GetParameter("key")).Contains("2");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RequestMessage_ParseQuery_SingleKey_MultipleValuesCommaSeparated()
|
||||
{
|
||||
// Assign
|
||||
var request = new RequestMessage(new UrlDetails("http://localhost?key=1,2,3"), "POST", ClientIp);
|
||||
|
||||
// Assert
|
||||
Check.That(request.GetParameter("key")).Contains("1");
|
||||
Check.That(request.GetParameter("key")).Contains("2");
|
||||
Check.That(request.GetParameter("key")).Contains("3");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RequestMessage_ParseQuery_SingleKey_MultipleValues()
|
||||
{
|
||||
|
||||
@@ -1,13 +1,17 @@
|
||||
using System.Threading.Tasks;
|
||||
using Moq;
|
||||
using NFluent;
|
||||
using System.Threading.Tasks;
|
||||
using WireMock.Models;
|
||||
using WireMock.ResponseBuilders;
|
||||
using WireMock.Settings;
|
||||
using Xunit;
|
||||
|
||||
namespace WireMock.Net.Tests.ResponseBuilders
|
||||
{
|
||||
public class ResponseCreateTests
|
||||
{
|
||||
private readonly Mock<IFluentMockServerSettings> _settingsMock = new Mock<IFluentMockServerSettings>();
|
||||
|
||||
[Fact]
|
||||
public async Task Response_Create_Func()
|
||||
{
|
||||
@@ -18,7 +22,7 @@ namespace WireMock.Net.Tests.ResponseBuilders
|
||||
var response = Response.Create(() => responseMessage);
|
||||
|
||||
// Act
|
||||
var providedResponse = await response.ProvideResponseAsync(request);
|
||||
var providedResponse = await response.ProvideResponseAsync(request, _settingsMock.Object);
|
||||
|
||||
// Assert
|
||||
Check.That(providedResponse).Equals(responseMessage);
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
using FluentAssertions;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using WireMock.RequestBuilders;
|
||||
using WireMock.ResponseBuilders;
|
||||
using WireMock.Server;
|
||||
using Xunit;
|
||||
|
||||
namespace WireMock.Net.Tests.ResponseBuilders
|
||||
{
|
||||
public class ResponseWithBodyFromFileTests
|
||||
{
|
||||
[Fact]
|
||||
public async Task Response_ProvideResponse_WithBodyFromFile()
|
||||
{
|
||||
// Arrange
|
||||
var server = FluentMockServer.Start();
|
||||
|
||||
string path = Path.Combine(Directory.GetCurrentDirectory(), "__admin", "mappings", "MyXmlResponse.xml");
|
||||
|
||||
server
|
||||
.Given(
|
||||
Request
|
||||
.Create()
|
||||
.UsingGet()
|
||||
.WithPath("/v1/content")
|
||||
)
|
||||
.RespondWith(
|
||||
Response
|
||||
.Create()
|
||||
.WithStatusCode(HttpStatusCode.OK)
|
||||
.WithHeader("Content-Type", "application/xml")
|
||||
.WithBodyFromFile(path)
|
||||
);
|
||||
|
||||
// Act
|
||||
var response1 = await new HttpClient().GetStringAsync("http://localhost:" + server.Ports[0] + "/v1/content");
|
||||
var response2 = await new HttpClient().GetStringAsync("http://localhost:" + server.Ports[0] + "/v1/content");
|
||||
var response3 = await new HttpClient().GetStringAsync("http://localhost:" + server.Ports[0] + "/v1/content");
|
||||
|
||||
// Assert
|
||||
response1.Should().Contain("<hello>world</hello>");
|
||||
response2.Should().Contain("<hello>world</hello>");
|
||||
response3.Should().Contain("<hello>world</hello>");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,12 @@
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Moq;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using NFluent;
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using WireMock.Models;
|
||||
using WireMock.ResponseBuilders;
|
||||
using WireMock.Settings;
|
||||
using WireMock.Util;
|
||||
using Xunit;
|
||||
|
||||
@@ -10,6 +14,7 @@ namespace WireMock.Net.Tests.ResponseBuilders
|
||||
{
|
||||
public class ResponseWithBodyTests
|
||||
{
|
||||
private readonly Mock<IFluentMockServerSettings> _settingsMock = new Mock<IFluentMockServerSettings>();
|
||||
private const string ClientIp = "::1";
|
||||
|
||||
[Fact]
|
||||
@@ -26,7 +31,7 @@ namespace WireMock.Net.Tests.ResponseBuilders
|
||||
var response = Response.Create().WithBody(new byte[] { 48, 49 }, BodyDestinationFormat.String, Encoding.ASCII);
|
||||
|
||||
// act
|
||||
var responseMessage = await response.ProvideResponseAsync(request);
|
||||
var responseMessage = await response.ProvideResponseAsync(request, _settingsMock.Object);
|
||||
|
||||
// then
|
||||
Check.That(responseMessage.BodyData.BodyAsString).Equals("01");
|
||||
@@ -48,7 +53,7 @@ namespace WireMock.Net.Tests.ResponseBuilders
|
||||
var response = Response.Create().WithBody(new byte[] { 48, 49 }, BodyDestinationFormat.SameAsSource, Encoding.ASCII);
|
||||
|
||||
// act
|
||||
var responseMessage = await response.ProvideResponseAsync(request);
|
||||
var responseMessage = await response.ProvideResponseAsync(request, _settingsMock.Object);
|
||||
|
||||
// then
|
||||
Check.That(responseMessage.BodyData.BodyAsBytes).ContainsExactly(new byte[] { 48, 49 });
|
||||
@@ -70,7 +75,7 @@ namespace WireMock.Net.Tests.ResponseBuilders
|
||||
var response = Response.Create().WithBody("test", null, Encoding.ASCII);
|
||||
|
||||
// act
|
||||
var responseMessage = await response.ProvideResponseAsync(request);
|
||||
var responseMessage = await response.ProvideResponseAsync(request, _settingsMock.Object);
|
||||
|
||||
// then
|
||||
Check.That(responseMessage.BodyData.BodyAsString).Equals("test");
|
||||
@@ -92,7 +97,7 @@ namespace WireMock.Net.Tests.ResponseBuilders
|
||||
var response = Response.Create().WithBodyAsJson(x, Encoding.ASCII);
|
||||
|
||||
// act
|
||||
var responseMessage = await response.ProvideResponseAsync(request);
|
||||
var responseMessage = await response.ProvideResponseAsync(request, _settingsMock.Object);
|
||||
|
||||
// then
|
||||
Check.That(responseMessage.BodyData.BodyAsJson).Equals(x);
|
||||
@@ -114,7 +119,7 @@ namespace WireMock.Net.Tests.ResponseBuilders
|
||||
var response = Response.Create().WithBodyAsJson(x, true);
|
||||
|
||||
// act
|
||||
var responseMessage = await response.ProvideResponseAsync(request);
|
||||
var responseMessage = await response.ProvideResponseAsync(request, _settingsMock.Object);
|
||||
|
||||
// then
|
||||
Check.That(responseMessage.BodyData.BodyAsJson).Equals(x);
|
||||
@@ -130,7 +135,7 @@ namespace WireMock.Net.Tests.ResponseBuilders
|
||||
var response = Response.Create().WithBody("r", BodyDestinationFormat.SameAsSource, Encoding.ASCII);
|
||||
|
||||
// Act
|
||||
var responseMessage = await response.ProvideResponseAsync(request);
|
||||
var responseMessage = await response.ProvideResponseAsync(request, _settingsMock.Object);
|
||||
|
||||
// Assert
|
||||
Check.That(responseMessage.BodyData.BodyAsBytes).IsNull();
|
||||
@@ -148,7 +153,7 @@ namespace WireMock.Net.Tests.ResponseBuilders
|
||||
var response = Response.Create().WithBody("r", BodyDestinationFormat.Bytes, Encoding.ASCII);
|
||||
|
||||
// Act
|
||||
var responseMessage = await response.ProvideResponseAsync(request);
|
||||
var responseMessage = await response.ProvideResponseAsync(request, _settingsMock.Object);
|
||||
|
||||
// Assert
|
||||
Check.That(responseMessage.BodyData.BodyAsString).IsNull();
|
||||
@@ -166,7 +171,7 @@ namespace WireMock.Net.Tests.ResponseBuilders
|
||||
var response = Response.Create().WithBody("{ \"value\": 42 }", BodyDestinationFormat.Json, Encoding.ASCII);
|
||||
|
||||
// Act
|
||||
var responseMessage = await response.ProvideResponseAsync(request);
|
||||
var responseMessage = await response.ProvideResponseAsync(request, _settingsMock.Object);
|
||||
|
||||
// Assert
|
||||
Check.That(responseMessage.BodyData.BodyAsString).IsNull();
|
||||
@@ -188,7 +193,7 @@ namespace WireMock.Net.Tests.ResponseBuilders
|
||||
.WithBody(req => $"path: {req.Path}");
|
||||
|
||||
// Act
|
||||
var responseMessage = await response.ProvideResponseAsync(request);
|
||||
var responseMessage = await response.ProvideResponseAsync(request, _settingsMock.Object);
|
||||
|
||||
// Assert
|
||||
Check.That(responseMessage.BodyData.BodyAsString).IsEqualTo("path: /test");
|
||||
@@ -199,5 +204,84 @@ namespace WireMock.Net.Tests.ResponseBuilders
|
||||
Check.That(responseMessage.Headers["H1"].ToString()).IsEqualTo("X1");
|
||||
Check.That(responseMessage.Headers["H2"].ToString()).IsEqualTo("X2");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Response_ProvideResponse_WithJsonBodyAndTransform_Func()
|
||||
{
|
||||
// Assign
|
||||
const int request1Id = 1;
|
||||
const int request2Id = 2;
|
||||
|
||||
var request1 = new RequestMessage(new UrlDetails($"http://localhost/test?id={request1Id}"), "GET", ClientIp);
|
||||
var request2 = new RequestMessage(new UrlDetails($"http://localhost/test?id={request2Id}"), "GET", ClientIp);
|
||||
|
||||
var response = Response.Create()
|
||||
.WithStatusCode(200)
|
||||
.WithBodyAsJson(JObject.Parse("{ \"id\": \"{{request.query.id}}\" }"))
|
||||
.WithTransformer();
|
||||
|
||||
// Act
|
||||
var response1Message = await response.ProvideResponseAsync(request1, _settingsMock.Object);
|
||||
var response2Message = await response.ProvideResponseAsync(request2, _settingsMock.Object);
|
||||
|
||||
// Assert
|
||||
Check.That(((JToken)response1Message.BodyData.BodyAsJson).SelectToken("id")?.Value<int>()).IsEqualTo(request1Id);
|
||||
Check.That(response1Message.BodyData.BodyAsBytes).IsNull();
|
||||
Check.That(response1Message.BodyData.BodyAsString).IsNull();
|
||||
Check.That(response1Message.StatusCode).IsEqualTo(200);
|
||||
|
||||
Check.That(((JToken)response2Message.BodyData.BodyAsJson).SelectToken("id")?.Value<int>()).IsEqualTo(request2Id);
|
||||
Check.That(response2Message.BodyData.BodyAsBytes).IsNull();
|
||||
Check.That(response2Message.BodyData.BodyAsString).IsNull();
|
||||
Check.That(response2Message.StatusCode).IsEqualTo(200);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Response_ProvideResponse_WithBodyAsFile()
|
||||
{
|
||||
var fileContents = "testFileContents" + Guid.NewGuid();
|
||||
var bodyDataAsFile = new BodyData { BodyAsFile = fileContents };
|
||||
|
||||
var request1 = new RequestMessage(new UrlDetails("http://localhost/__admin/files/filename.txt"), "PUT", ClientIp, bodyDataAsFile);
|
||||
|
||||
var response = Response.Create().WithStatusCode(200).WithBody(fileContents);
|
||||
|
||||
var provideResponseAsync = await response.ProvideResponseAsync(request1, _settingsMock.Object);
|
||||
|
||||
Check.That(provideResponseAsync.StatusCode).IsEqualTo(200);
|
||||
Check.That(provideResponseAsync.BodyData.BodyAsString).Contains(fileContents);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Response_ProvideResponse_WithResponseAsFile()
|
||||
{
|
||||
var fileContents = "testFileContents" + Guid.NewGuid();
|
||||
var bodyDataAsFile = new BodyData { BodyAsFile = fileContents };
|
||||
|
||||
var request1 = new RequestMessage(new UrlDetails("http://localhost/__admin/files/filename.txt"), "GET", ClientIp, bodyDataAsFile);
|
||||
|
||||
var response = Response.Create().WithStatusCode(200).WithBody(fileContents);
|
||||
|
||||
var provideResponseAsync = await response.ProvideResponseAsync(request1, _settingsMock.Object);
|
||||
|
||||
Check.That(provideResponseAsync.StatusCode).IsEqualTo(200);
|
||||
Check.That(provideResponseAsync.BodyData.BodyAsString).Contains(fileContents);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Response_ProvideResponse_WithResponseDeleted()
|
||||
{
|
||||
var fileContents = "testFileContents" + Guid.NewGuid();
|
||||
var bodyDataAsFile = new BodyData { BodyAsFile = fileContents };
|
||||
|
||||
var request1 = new RequestMessage(new UrlDetails("http://localhost/__admin/files/filename.txt"), "DELETE", ClientIp, bodyDataAsFile);
|
||||
|
||||
var response = Response.Create().WithStatusCode(200).WithBody("File deleted.");
|
||||
|
||||
var provideResponseAsync = await response.ProvideResponseAsync(request1, _settingsMock.Object);
|
||||
|
||||
Check.That(provideResponseAsync.StatusCode).IsEqualTo(200);
|
||||
Check.That(provideResponseAsync.BodyData.BodyAsString).Contains("File deleted.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
using System.Threading.Tasks;
|
||||
using Moq;
|
||||
using NFluent;
|
||||
using System.Threading.Tasks;
|
||||
using WireMock.Models;
|
||||
using WireMock.ResponseBuilders;
|
||||
using WireMock.Settings;
|
||||
using WireMock.Util;
|
||||
using Xunit;
|
||||
|
||||
@@ -9,6 +11,8 @@ namespace WireMock.Net.Tests.ResponseBuilders
|
||||
{
|
||||
public class ResponseWithCallbackTests
|
||||
{
|
||||
private readonly Mock<IFluentMockServerSettings> _settingsMock = new Mock<IFluentMockServerSettings>();
|
||||
|
||||
[Fact]
|
||||
public async Task Response_WithCallback()
|
||||
{
|
||||
@@ -17,7 +21,7 @@ namespace WireMock.Net.Tests.ResponseBuilders
|
||||
var response = Response.Create().WithCallback(req => new ResponseMessage { BodyData = new BodyData { DetectedBodyType = BodyType.String, BodyAsString = req.Path + "Bar" }, StatusCode = 302 });
|
||||
|
||||
// Act
|
||||
var responseMessage = await response.ProvideResponseAsync(request);
|
||||
var responseMessage = await response.ProvideResponseAsync(request, _settingsMock.Object);
|
||||
|
||||
// Assert
|
||||
Check.That(responseMessage.BodyData.BodyAsString).IsEqualTo("/fooBar");
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
using Moq;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using NFluent;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using WireMock.Handlers;
|
||||
using WireMock.Models;
|
||||
using WireMock.ResponseBuilders;
|
||||
using WireMock.Settings;
|
||||
using Xunit;
|
||||
|
||||
namespace WireMock.Net.Tests.ResponseBuilders
|
||||
{
|
||||
public class ResponseWithHandlebarsFileTests
|
||||
{
|
||||
private readonly Mock<IFileSystemHandler> _filesystemHandlerMock;
|
||||
private readonly Mock<IFluentMockServerSettings> _settingsMock;
|
||||
private const string ClientIp = "::1";
|
||||
|
||||
public ResponseWithHandlebarsFileTests()
|
||||
{
|
||||
_filesystemHandlerMock = new Mock<IFileSystemHandler>(MockBehavior.Strict);
|
||||
_filesystemHandlerMock.Setup(fs => fs.ReadResponseBodyAsString(It.IsAny<string>())).Returns("abc");
|
||||
|
||||
_settingsMock = new Mock<IFluentMockServerSettings>();
|
||||
_settingsMock.SetupGet(s => s.FileSystemHandler).Returns(_filesystemHandlerMock.Object);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Response_ProvideResponseAsync_Handlebars_File()
|
||||
{
|
||||
// Assign
|
||||
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "GET", ClientIp);
|
||||
|
||||
var response = Response.Create()
|
||||
.WithBodyAsJson(new
|
||||
{
|
||||
Data = "{{File \"x.json\"}}"
|
||||
})
|
||||
.WithTransformer();
|
||||
|
||||
// Act
|
||||
var responseMessage = await response.ProvideResponseAsync(request, _settingsMock.Object);
|
||||
|
||||
// Assert
|
||||
JObject j = JObject.FromObject(responseMessage.BodyData.BodyAsJson);
|
||||
Check.That(j["Data"].Value<string>()).Equals("abc");
|
||||
|
||||
// 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);
|
||||
|
||||
var response = Response.Create()
|
||||
.WithBodyAsJson(new
|
||||
{
|
||||
Data = "{{File \"{{request.query.id}}.json\"}}"
|
||||
})
|
||||
.WithTransformer();
|
||||
|
||||
// Act
|
||||
var responseMessage = await response.ProvideResponseAsync(request, _settingsMock.Object);
|
||||
|
||||
// Assert
|
||||
JObject j = JObject.FromObject(responseMessage.BodyData.BodyAsJson);
|
||||
Check.That(j["Data"].Value<string>()).Equals("abc");
|
||||
|
||||
// Verify
|
||||
_filesystemHandlerMock.Verify(fs => fs.ReadResponseBodyAsString("x.json"), Times.Once);
|
||||
_filesystemHandlerMock.VerifyNoOtherCalls();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Response_ProvideResponseAsync_Handlebars_File_WithMissingArgument_ThrowsArgumentOutOfRangeException()
|
||||
{
|
||||
// Assign
|
||||
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "GET", ClientIp);
|
||||
|
||||
var response = Response.Create()
|
||||
.WithBodyAsJson(new
|
||||
{
|
||||
Data = "{{File}}"
|
||||
})
|
||||
.WithTransformer();
|
||||
|
||||
// Act
|
||||
Check.ThatAsyncCode(() => response.ProvideResponseAsync(request, _settingsMock.Object)).Throws<ArgumentOutOfRangeException>();
|
||||
|
||||
// Verify
|
||||
_filesystemHandlerMock.Verify(fs => fs.ReadResponseBodyAsString(It.IsAny<string>()), Times.Never);
|
||||
_filesystemHandlerMock.VerifyNoOtherCalls();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,11 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Moq;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using NFluent;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using WireMock.Models;
|
||||
using WireMock.ResponseBuilders;
|
||||
using WireMock.Settings;
|
||||
using WireMock.Util;
|
||||
using Xunit;
|
||||
|
||||
@@ -11,6 +13,7 @@ namespace WireMock.Net.Tests.ResponseBuilders
|
||||
{
|
||||
public class ResponseWithHandlebarsJsonPathTests
|
||||
{
|
||||
private readonly Mock<IFluentMockServerSettings> _settingsMock = new Mock<IFluentMockServerSettings>();
|
||||
private const string ClientIp = "::1";
|
||||
|
||||
[Fact]
|
||||
@@ -60,7 +63,7 @@ namespace WireMock.Net.Tests.ResponseBuilders
|
||||
.WithTransformer();
|
||||
|
||||
// Act
|
||||
var responseMessage = await response.ProvideResponseAsync(request);
|
||||
var responseMessage = await response.ProvideResponseAsync(request, _settingsMock.Object);
|
||||
|
||||
// Assert
|
||||
JObject j = JObject.FromObject(responseMessage.BodyData.BodyAsJson);
|
||||
@@ -86,7 +89,7 @@ namespace WireMock.Net.Tests.ResponseBuilders
|
||||
.WithTransformer();
|
||||
|
||||
// Act
|
||||
var responseMessage = await response.ProvideResponseAsync(request);
|
||||
var responseMessage = await response.ProvideResponseAsync(request, _settingsMock.Object);
|
||||
|
||||
// Assert
|
||||
JObject j = JObject.FromObject(responseMessage.BodyData.BodyAsJson);
|
||||
@@ -140,7 +143,7 @@ namespace WireMock.Net.Tests.ResponseBuilders
|
||||
.WithTransformer();
|
||||
|
||||
// Act
|
||||
var responseMessage = await response.ProvideResponseAsync(request);
|
||||
var responseMessage = await response.ProvideResponseAsync(request, _settingsMock.Object);
|
||||
|
||||
// Assert
|
||||
Check.That(responseMessage.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}}}");
|
||||
@@ -193,7 +196,7 @@ namespace WireMock.Net.Tests.ResponseBuilders
|
||||
.WithTransformer();
|
||||
|
||||
// Act
|
||||
var responseMessage = await response.ProvideResponseAsync(request);
|
||||
var responseMessage = await response.ProvideResponseAsync(request, _settingsMock.Object);
|
||||
|
||||
// Assert
|
||||
Check.That(responseMessage.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}}}");
|
||||
@@ -246,7 +249,7 @@ namespace WireMock.Net.Tests.ResponseBuilders
|
||||
.WithTransformer();
|
||||
|
||||
// Act
|
||||
var responseMessage = await response.ProvideResponseAsync(request);
|
||||
var responseMessage = await response.ProvideResponseAsync(request, _settingsMock.Object);
|
||||
|
||||
// Assert
|
||||
Check.That(responseMessage.BodyData.BodyAsString).Equals("%0:Anvil%%1:Elbow Grease%");
|
||||
@@ -299,7 +302,7 @@ namespace WireMock.Net.Tests.ResponseBuilders
|
||||
.WithTransformer();
|
||||
|
||||
// Act
|
||||
var responseMessage = await response.ProvideResponseAsync(request);
|
||||
var responseMessage = await response.ProvideResponseAsync(request, _settingsMock.Object);
|
||||
|
||||
// Assert
|
||||
Check.That(responseMessage.BodyData.BodyAsString).Equals("%0:Anvil%%1:Elbow Grease%");
|
||||
@@ -328,7 +331,7 @@ namespace WireMock.Net.Tests.ResponseBuilders
|
||||
.WithTransformer();
|
||||
|
||||
// Act
|
||||
Check.ThatAsyncCode(() => response.ProvideResponseAsync(request)).Throws<ArgumentNullException>();
|
||||
Check.ThatAsyncCode(() => response.ProvideResponseAsync(request, _settingsMock.Object)).Throws<ArgumentNullException>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,11 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Moq;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using NFluent;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using WireMock.Models;
|
||||
using WireMock.ResponseBuilders;
|
||||
using WireMock.Settings;
|
||||
using WireMock.Util;
|
||||
using Xunit;
|
||||
|
||||
@@ -11,11 +13,13 @@ namespace WireMock.Net.Tests.ResponseBuilders
|
||||
{
|
||||
public class ResponseWithHandlebarsLinqTests
|
||||
{
|
||||
private readonly Mock<IFluentMockServerSettings> _settingsMock = new Mock<IFluentMockServerSettings>();
|
||||
|
||||
[Fact]
|
||||
public async Task Response_ProvideResponse_Handlebars_Linq1_String0()
|
||||
{
|
||||
// Assign
|
||||
var body = new BodyData { };
|
||||
var body = new BodyData();
|
||||
|
||||
var request = new RequestMessage(new UrlDetails("http://localhost:1234/pathtest"), "POST", "::1", body);
|
||||
|
||||
@@ -25,7 +29,7 @@ namespace WireMock.Net.Tests.ResponseBuilders
|
||||
.WithTransformer();
|
||||
|
||||
// Act
|
||||
var responseMessage = await response.ProvideResponseAsync(request);
|
||||
var responseMessage = await response.ProvideResponseAsync(request, _settingsMock.Object);
|
||||
|
||||
// Assert
|
||||
JObject j = JObject.FromObject(responseMessage.BodyData.BodyAsJson);
|
||||
@@ -55,7 +59,7 @@ namespace WireMock.Net.Tests.ResponseBuilders
|
||||
.WithTransformer();
|
||||
|
||||
// Act
|
||||
var responseMessage = await response.ProvideResponseAsync(request);
|
||||
var responseMessage = await response.ProvideResponseAsync(request, _settingsMock.Object);
|
||||
|
||||
// Assert
|
||||
JObject j = JObject.FromObject(responseMessage.BodyData.BodyAsJson);
|
||||
@@ -85,7 +89,7 @@ namespace WireMock.Net.Tests.ResponseBuilders
|
||||
.WithTransformer();
|
||||
|
||||
// Act
|
||||
var responseMessage = await response.ProvideResponseAsync(request);
|
||||
var responseMessage = await response.ProvideResponseAsync(request, _settingsMock.Object);
|
||||
|
||||
// Assert
|
||||
JObject j = JObject.FromObject(responseMessage.BodyData.BodyAsJson);
|
||||
@@ -115,7 +119,7 @@ namespace WireMock.Net.Tests.ResponseBuilders
|
||||
.WithTransformer();
|
||||
|
||||
// Act
|
||||
var responseMessage = await response.ProvideResponseAsync(request);
|
||||
var responseMessage = await response.ProvideResponseAsync(request, _settingsMock.Object);
|
||||
|
||||
// Assert
|
||||
JObject j = JObject.FromObject(responseMessage.BodyData.BodyAsJson);
|
||||
@@ -140,14 +144,14 @@ namespace WireMock.Net.Tests.ResponseBuilders
|
||||
.WithTransformer();
|
||||
|
||||
// Act
|
||||
Check.ThatAsyncCode(() => response.ProvideResponseAsync(request)).Throws<NotSupportedException>();
|
||||
Check.ThatAsyncCode(() => response.ProvideResponseAsync(request, _settingsMock.Object)).Throws<NotSupportedException>();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Response_ProvideResponse_Handlebars_Linq1_Throws_ArgumentNullException()
|
||||
{
|
||||
// Assign
|
||||
var body = new BodyData { };
|
||||
var body = new BodyData();
|
||||
|
||||
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", "::1", body);
|
||||
|
||||
@@ -156,14 +160,14 @@ namespace WireMock.Net.Tests.ResponseBuilders
|
||||
.WithTransformer();
|
||||
|
||||
// Act
|
||||
Check.ThatAsyncCode(() => response.ProvideResponseAsync(request)).Throws<ArgumentNullException>();
|
||||
Check.ThatAsyncCode(() => response.ProvideResponseAsync(request, _settingsMock.Object)).Throws<ArgumentNullException>();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Response_ProvideResponse_Handlebars_Linq1_Throws_ArgumentException()
|
||||
{
|
||||
// Assign
|
||||
var body = new BodyData { };
|
||||
var body = new BodyData();
|
||||
|
||||
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", "::1", body);
|
||||
|
||||
@@ -172,7 +176,7 @@ namespace WireMock.Net.Tests.ResponseBuilders
|
||||
.WithTransformer();
|
||||
|
||||
// Act
|
||||
Check.ThatAsyncCode(() => response.ProvideResponseAsync(request)).Throws<ArgumentException>();
|
||||
Check.ThatAsyncCode(() => response.ProvideResponseAsync(request, _settingsMock.Object)).Throws<ArgumentException>();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -196,7 +200,7 @@ namespace WireMock.Net.Tests.ResponseBuilders
|
||||
.WithTransformer();
|
||||
|
||||
// Act
|
||||
var responseMessage = await response.ProvideResponseAsync(request);
|
||||
var responseMessage = await response.ProvideResponseAsync(request, _settingsMock.Object);
|
||||
|
||||
// Assert
|
||||
JObject j = JObject.FromObject(responseMessage.BodyData.BodyAsJson);
|
||||
@@ -224,7 +228,7 @@ namespace WireMock.Net.Tests.ResponseBuilders
|
||||
.WithTransformer();
|
||||
|
||||
// Act
|
||||
var responseMessage = await response.ProvideResponseAsync(request);
|
||||
var responseMessage = await response.ProvideResponseAsync(request, _settingsMock.Object);
|
||||
|
||||
// Assert
|
||||
JObject j = JObject.FromObject(responseMessage.BodyData.BodyAsJson);
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Moq;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using NFluent;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using WireMock.Models;
|
||||
using WireMock.ResponseBuilders;
|
||||
using WireMock.Settings;
|
||||
using Xunit;
|
||||
|
||||
namespace WireMock.Net.Tests.ResponseBuilders
|
||||
{
|
||||
public class ResponseWithHandlebarsRandomTests
|
||||
{
|
||||
private readonly Mock<IFluentMockServerSettings> _settingsMock = new Mock<IFluentMockServerSettings>();
|
||||
private const string ClientIp = "::1";
|
||||
|
||||
[Fact]
|
||||
@@ -30,7 +32,7 @@ namespace WireMock.Net.Tests.ResponseBuilders
|
||||
.WithTransformer();
|
||||
|
||||
// Act
|
||||
var responseMessage = await response.ProvideResponseAsync(request);
|
||||
var responseMessage = await response.ProvideResponseAsync(request, _settingsMock.Object);
|
||||
|
||||
// Assert
|
||||
JObject j = JObject.FromObject(responseMessage.BodyData.BodyAsJson);
|
||||
@@ -53,7 +55,7 @@ namespace WireMock.Net.Tests.ResponseBuilders
|
||||
.WithTransformer();
|
||||
|
||||
// Act
|
||||
var responseMessage = await response.ProvideResponseAsync(request);
|
||||
var responseMessage = await response.ProvideResponseAsync(request, _settingsMock.Object);
|
||||
|
||||
// Assert
|
||||
JObject j = JObject.FromObject(responseMessage.BodyData.BodyAsJson);
|
||||
@@ -75,7 +77,7 @@ namespace WireMock.Net.Tests.ResponseBuilders
|
||||
.WithTransformer();
|
||||
|
||||
// Act
|
||||
var responseMessage = await response.ProvideResponseAsync(request);
|
||||
var responseMessage = await response.ProvideResponseAsync(request, _settingsMock.Object);
|
||||
|
||||
// Assert
|
||||
JObject j = JObject.FromObject(responseMessage.BodyData.BodyAsJson);
|
||||
@@ -99,7 +101,7 @@ namespace WireMock.Net.Tests.ResponseBuilders
|
||||
.WithTransformer();
|
||||
|
||||
// Act
|
||||
var responseMessage = await response.ProvideResponseAsync(request);
|
||||
var responseMessage = await response.ProvideResponseAsync(request, _settingsMock.Object);
|
||||
|
||||
// Assert
|
||||
JObject j = JObject.FromObject(responseMessage.BodyData.BodyAsJson);
|
||||
@@ -121,7 +123,7 @@ namespace WireMock.Net.Tests.ResponseBuilders
|
||||
.WithTransformer();
|
||||
|
||||
// Act
|
||||
var responseMessage = await response.ProvideResponseAsync(request);
|
||||
var responseMessage = await response.ProvideResponseAsync(request, _settingsMock.Object);
|
||||
|
||||
// Assert
|
||||
JObject j = JObject.FromObject(responseMessage.BodyData.BodyAsJson);
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Moq;
|
||||
using NFluent;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using WireMock.Models;
|
||||
using WireMock.ResponseBuilders;
|
||||
using WireMock.Settings;
|
||||
using WireMock.Util;
|
||||
using Xunit;
|
||||
|
||||
@@ -10,6 +12,7 @@ namespace WireMock.Net.Tests.ResponseBuilders
|
||||
{
|
||||
public class ResponseWithHandlebarsRegexTests
|
||||
{
|
||||
private readonly Mock<IFluentMockServerSettings> _settingsMock = new Mock<IFluentMockServerSettings>();
|
||||
private const string ClientIp = "::1";
|
||||
|
||||
[Fact]
|
||||
@@ -25,7 +28,7 @@ namespace WireMock.Net.Tests.ResponseBuilders
|
||||
.WithTransformer();
|
||||
|
||||
// Act
|
||||
var responseMessage = await response.ProvideResponseAsync(request);
|
||||
var responseMessage = await response.ProvideResponseAsync(request, _settingsMock.Object);
|
||||
|
||||
// assert
|
||||
Check.That(responseMessage.BodyData.BodyAsString).Equals("abc");
|
||||
@@ -44,7 +47,7 @@ namespace WireMock.Net.Tests.ResponseBuilders
|
||||
.WithTransformer();
|
||||
|
||||
// Act
|
||||
var responseMessage = await response.ProvideResponseAsync(request);
|
||||
var responseMessage = await response.ProvideResponseAsync(request, _settingsMock.Object);
|
||||
|
||||
// assert
|
||||
Check.That(responseMessage.BodyData.BodyAsString).Equals("");
|
||||
@@ -63,7 +66,7 @@ namespace WireMock.Net.Tests.ResponseBuilders
|
||||
.WithTransformer();
|
||||
|
||||
// Act
|
||||
var responseMessage = await response.ProvideResponseAsync(request);
|
||||
var responseMessage = await response.ProvideResponseAsync(request, _settingsMock.Object);
|
||||
|
||||
// assert
|
||||
Check.That(responseMessage.BodyData.BodyAsString).Equals("d");
|
||||
@@ -82,7 +85,7 @@ namespace WireMock.Net.Tests.ResponseBuilders
|
||||
.WithTransformer();
|
||||
|
||||
// Act
|
||||
var responseMessage = await response.ProvideResponseAsync(request);
|
||||
var responseMessage = await response.ProvideResponseAsync(request, _settingsMock.Object);
|
||||
|
||||
// assert
|
||||
Check.That(responseMessage.BodyData.BodyAsString).Equals("5000-https");
|
||||
@@ -101,7 +104,7 @@ namespace WireMock.Net.Tests.ResponseBuilders
|
||||
.WithTransformer();
|
||||
|
||||
// Act
|
||||
var responseMessage = await response.ProvideResponseAsync(request);
|
||||
var responseMessage = await response.ProvideResponseAsync(request, _settingsMock.Object);
|
||||
|
||||
// assert
|
||||
Check.That(responseMessage.BodyData.BodyAsString).Equals("");
|
||||
@@ -120,7 +123,7 @@ namespace WireMock.Net.Tests.ResponseBuilders
|
||||
.WithTransformer();
|
||||
|
||||
// Act
|
||||
var responseMessage = await response.ProvideResponseAsync(request);
|
||||
var responseMessage = await response.ProvideResponseAsync(request, _settingsMock.Object);
|
||||
|
||||
// assert
|
||||
Check.That(responseMessage.BodyData.BodyAsString).Equals("x");
|
||||
@@ -139,7 +142,7 @@ namespace WireMock.Net.Tests.ResponseBuilders
|
||||
.WithTransformer();
|
||||
|
||||
// Act and Assert
|
||||
Check.ThatAsyncCode(() => response.ProvideResponseAsync(request)).Throws<NotSupportedException>();
|
||||
Check.ThatAsyncCode(() => response.ProvideResponseAsync(request, _settingsMock.Object)).Throws<NotSupportedException>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,10 +2,12 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Moq;
|
||||
using Newtonsoft.Json;
|
||||
using NFluent;
|
||||
using WireMock.Models;
|
||||
using WireMock.ResponseBuilders;
|
||||
using WireMock.Settings;
|
||||
using WireMock.Util;
|
||||
using Xunit;
|
||||
#if NET452
|
||||
@@ -18,6 +20,7 @@ namespace WireMock.Net.Tests.ResponseBuilders
|
||||
{
|
||||
public class ResponseWithHandlebarsTests
|
||||
{
|
||||
private readonly Mock<IFluentMockServerSettings> _settingsMock = new Mock<IFluentMockServerSettings>();
|
||||
private const string ClientIp = "::1";
|
||||
|
||||
[Fact]
|
||||
@@ -38,7 +41,7 @@ namespace WireMock.Net.Tests.ResponseBuilders
|
||||
.WithTransformer();
|
||||
|
||||
// Act
|
||||
var responseMessage = await response.ProvideResponseAsync(request);
|
||||
var responseMessage = await response.ProvideResponseAsync(request, _settingsMock.Object);
|
||||
|
||||
// Assert
|
||||
Check.That(JsonConvert.SerializeObject(responseMessage.BodyData.BodyAsJson)).Equals("{\"x\":\"test /foo_object\"}");
|
||||
@@ -60,7 +63,7 @@ namespace WireMock.Net.Tests.ResponseBuilders
|
||||
.WithTransformer();
|
||||
|
||||
// Act
|
||||
var responseMessage = await response.ProvideResponseAsync(request);
|
||||
var responseMessage = await response.ProvideResponseAsync(request, _settingsMock.Object);
|
||||
|
||||
// Assert
|
||||
Check.That(responseMessage.BodyData.BodyAsString).Equals("test http://localhost/foo /foo POSt");
|
||||
@@ -78,7 +81,7 @@ namespace WireMock.Net.Tests.ResponseBuilders
|
||||
.WithTransformer();
|
||||
|
||||
// Act
|
||||
var responseMessage = await response.ProvideResponseAsync(request);
|
||||
var responseMessage = await response.ProvideResponseAsync(request, _settingsMock.Object);
|
||||
|
||||
// Assert
|
||||
Check.That(responseMessage.BodyData.BodyAsString).Equals("http://localhost/a/b http://localhost/wiremock/a/b /a/b /wiremock/a/b");
|
||||
@@ -96,7 +99,7 @@ namespace WireMock.Net.Tests.ResponseBuilders
|
||||
.WithTransformer();
|
||||
|
||||
// Act
|
||||
var responseMessage = await response.ProvideResponseAsync(request);
|
||||
var responseMessage = await response.ProvideResponseAsync(request, _settingsMock.Object);
|
||||
|
||||
// Assert
|
||||
Check.That(responseMessage.BodyData.BodyAsString).Equals("a wiremock");
|
||||
@@ -118,7 +121,7 @@ namespace WireMock.Net.Tests.ResponseBuilders
|
||||
.WithTransformer();
|
||||
|
||||
// Act
|
||||
var responseMessage = await response.ProvideResponseAsync(request);
|
||||
var responseMessage = await response.ProvideResponseAsync(request, _settingsMock.Object);
|
||||
|
||||
// Assert
|
||||
Check.That(responseMessage.BodyData.BodyAsString).Equals("test keya=1 idx=1 idx=2 keyb=5");
|
||||
@@ -138,7 +141,7 @@ namespace WireMock.Net.Tests.ResponseBuilders
|
||||
var response = Response.Create().WithHeader("x", "{{request.headers.Content-Type}}").WithBody("test").WithTransformer();
|
||||
|
||||
// Act
|
||||
var responseMessage = await response.ProvideResponseAsync(request);
|
||||
var responseMessage = await response.ProvideResponseAsync(request, _settingsMock.Object);
|
||||
|
||||
// Assert
|
||||
Check.That(responseMessage.BodyData.BodyAsString).Equals("test");
|
||||
@@ -160,7 +163,7 @@ namespace WireMock.Net.Tests.ResponseBuilders
|
||||
var response = Response.Create().WithHeader("x", "{{request.headers.Content-Type}}", "{{request.url}}").WithBody("test").WithTransformer();
|
||||
|
||||
// Act
|
||||
var responseMessage = await response.ProvideResponseAsync(request);
|
||||
var responseMessage = await response.ProvideResponseAsync(request, _settingsMock.Object);
|
||||
|
||||
// Assert
|
||||
Check.That(responseMessage.BodyData.BodyAsString).Equals("test");
|
||||
@@ -185,7 +188,7 @@ namespace WireMock.Net.Tests.ResponseBuilders
|
||||
.WithTransformer();
|
||||
|
||||
// Act
|
||||
var responseMessage = await response.ProvideResponseAsync(request);
|
||||
var responseMessage = await response.ProvideResponseAsync(request, _settingsMock.Object);
|
||||
|
||||
// Assert
|
||||
Check.That(responseMessage.BodyData.BodyAsString).Equals("test http://localhost:1234 1234 http localhost");
|
||||
@@ -209,10 +212,54 @@ namespace WireMock.Net.Tests.ResponseBuilders
|
||||
.WithTransformer();
|
||||
|
||||
// Act
|
||||
var responseMessage = await response.ProvideResponseAsync(request);
|
||||
var responseMessage = await response.ProvideResponseAsync(request, _settingsMock.Object);
|
||||
|
||||
// Assert
|
||||
Check.That(JsonConvert.SerializeObject(responseMessage.BodyData.BodyAsJson)).Equals("[\"first\",\"/foo_array\",\"test 1\",\"test 2\",\"last\"]");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Response_ProvideResponse_Handlebars_WithBodyAsFile()
|
||||
{
|
||||
// Assign
|
||||
var request = new RequestMessage(new UrlDetails("http://localhost/foo?MyUniqueNumber=1"), "GET", ClientIp);
|
||||
|
||||
var response = Response.Create()
|
||||
.WithTransformer()
|
||||
.WithBodyFromFile(@"c:\\{{request.query.MyUniqueNumber}}\test.xml"); // why use a \\ here ?
|
||||
|
||||
// Act
|
||||
var responseMessage = await response.ProvideResponseAsync(request, _settingsMock.Object);
|
||||
|
||||
// Assert
|
||||
Check.That(responseMessage.BodyData.BodyAsFile).Equals(@"c:\1\test.xml");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Response_ProvideResponse_Handlebars_WithBodyAsFile_JsonPath()
|
||||
{
|
||||
// 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);
|
||||
|
||||
string jsonPath = "\"$.MyUniqueNumber\"";
|
||||
var response = Response.Create()
|
||||
.WithTransformer()
|
||||
.WithBodyFromFile(@"c:\\{{JsonPath.SelectToken request.body " + jsonPath + "}}\\test.json"); // why use a \\ here ?
|
||||
|
||||
// Act
|
||||
var responseMessage = await response.ProvideResponseAsync(request, _settingsMock.Object);
|
||||
|
||||
// Assert
|
||||
Check.That(responseMessage.BodyData.BodyAsFile).Equals(@"c:\1\test.json");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,17 @@
|
||||
using System.Threading.Tasks;
|
||||
using Moq;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using NFluent;
|
||||
using System.Threading.Tasks;
|
||||
using WireMock.Models;
|
||||
using WireMock.ResponseBuilders;
|
||||
using WireMock.Settings;
|
||||
using Xunit;
|
||||
|
||||
namespace WireMock.Net.Tests.ResponseBuilders
|
||||
{
|
||||
public class ResponseWithHandlebarsXegerTests
|
||||
{
|
||||
private readonly Mock<IFluentMockServerSettings> _settingsMock = new Mock<IFluentMockServerSettings>();
|
||||
private const string ClientIp = "::1";
|
||||
|
||||
[Fact]
|
||||
@@ -26,7 +29,7 @@ namespace WireMock.Net.Tests.ResponseBuilders
|
||||
.WithTransformer();
|
||||
|
||||
// Act
|
||||
var responseMessage = await response.ProvideResponseAsync(request);
|
||||
var responseMessage = await response.ProvideResponseAsync(request, _settingsMock.Object);
|
||||
|
||||
// Assert
|
||||
JObject j = JObject.FromObject(responseMessage.BodyData.BodyAsJson);
|
||||
@@ -49,7 +52,7 @@ namespace WireMock.Net.Tests.ResponseBuilders
|
||||
.WithTransformer();
|
||||
|
||||
// Act
|
||||
var responseMessage = await response.ProvideResponseAsync(request);
|
||||
var responseMessage = await response.ProvideResponseAsync(request, _settingsMock.Object);
|
||||
|
||||
// Assert
|
||||
JObject j = JObject.FromObject(responseMessage.BodyData.BodyAsJson);
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Moq;
|
||||
using NFluent;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using WireMock.Models;
|
||||
using WireMock.ResponseBuilders;
|
||||
using WireMock.Settings;
|
||||
using WireMock.Util;
|
||||
using Xunit;
|
||||
|
||||
@@ -10,6 +12,7 @@ namespace WireMock.Net.Tests.ResponseBuilders
|
||||
{
|
||||
public class ResponseWithHeadersTests
|
||||
{
|
||||
private readonly Mock<IFluentMockServerSettings> _settingsMock = new Mock<IFluentMockServerSettings>();
|
||||
private const string ClientIp = "::1";
|
||||
|
||||
[Theory]
|
||||
@@ -23,7 +26,7 @@ namespace WireMock.Net.Tests.ResponseBuilders
|
||||
IResponseBuilder builder = Response.Create().WithHeader(headerName, headerValue);
|
||||
|
||||
// Act
|
||||
var response = await builder.ProvideResponseAsync(requestMock);
|
||||
var response = await builder.ProvideResponseAsync(requestMock, _settingsMock.Object);
|
||||
|
||||
// Assert
|
||||
Check.That(response.Headers[headerName].ToString()).Equals(headerValue);
|
||||
@@ -39,7 +42,7 @@ namespace WireMock.Net.Tests.ResponseBuilders
|
||||
IResponseBuilder builder = Response.Create().WithHeader(headerName, headerValues);
|
||||
|
||||
// Act
|
||||
var response = await builder.ProvideResponseAsync(requestMock);
|
||||
var response = await builder.ProvideResponseAsync(requestMock, _settingsMock.Object);
|
||||
|
||||
// Assert
|
||||
Check.That(response.Headers[headerName].ToArray()).Equals(headerValues);
|
||||
@@ -54,7 +57,7 @@ namespace WireMock.Net.Tests.ResponseBuilders
|
||||
var response = Response.Create().WithHeaders(headers);
|
||||
|
||||
// Act
|
||||
var responseMessage = await response.ProvideResponseAsync(request);
|
||||
var responseMessage = await response.ProvideResponseAsync(request, _settingsMock.Object);
|
||||
|
||||
// Assert
|
||||
Check.That(responseMessage.Headers["h"]).ContainsExactly("x");
|
||||
@@ -69,7 +72,7 @@ namespace WireMock.Net.Tests.ResponseBuilders
|
||||
var response = Response.Create().WithHeaders(headers);
|
||||
|
||||
// Act
|
||||
var responseMessage = await response.ProvideResponseAsync(request);
|
||||
var responseMessage = await response.ProvideResponseAsync(request, _settingsMock.Object);
|
||||
|
||||
// Assert
|
||||
Check.That(responseMessage.Headers["h"]).ContainsExactly("x");
|
||||
@@ -84,7 +87,7 @@ namespace WireMock.Net.Tests.ResponseBuilders
|
||||
var response = Response.Create().WithHeaders(headers);
|
||||
|
||||
// Act
|
||||
var responseMessage = await response.ProvideResponseAsync(request);
|
||||
var responseMessage = await response.ProvideResponseAsync(request, _settingsMock.Object);
|
||||
|
||||
// Assert
|
||||
Check.That(responseMessage.Headers["h"]).ContainsExactly("x");
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
using System;
|
||||
using Moq;
|
||||
using NFluent;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using NFluent;
|
||||
using WireMock.Models;
|
||||
using WireMock.RequestBuilders;
|
||||
using WireMock.ResponseBuilders;
|
||||
using WireMock.Server;
|
||||
using WireMock.Settings;
|
||||
using WireMock.Util;
|
||||
using Xunit;
|
||||
|
||||
@@ -13,6 +15,7 @@ namespace WireMock.Net.Tests.ResponseBuilders
|
||||
{
|
||||
public class ResponseWithProxyTests : IDisposable
|
||||
{
|
||||
private readonly Mock<IFluentMockServerSettings> _settingsMock = new Mock<IFluentMockServerSettings>();
|
||||
private readonly FluentMockServer _server;
|
||||
private readonly Guid _guid;
|
||||
|
||||
@@ -30,11 +33,11 @@ namespace WireMock.Net.Tests.ResponseBuilders
|
||||
{
|
||||
// Assign
|
||||
var headers = new Dictionary<string, string[]> { { "Content-Type", new[] { "application/xml" } } };
|
||||
var request = new RequestMessage(new UrlDetails($"{_server.Urls[0]}/{_guid}"), "POST", "::1", new BodyData { DetectedBodyType = BodyType.Json, BodyAsJson = new { a = 1 } }, headers);
|
||||
var request = new RequestMessage(new UrlDetails($"{_server.Urls[0]}/{_guid}"), "POST", "::1", new BodyData { DetectedBodyType = BodyType.Json, BodyAsJson = new { a = 1 } }, headers);
|
||||
var response = Response.Create().WithProxy(_server.Urls[0]);
|
||||
|
||||
// Act
|
||||
var responseMessage = await response.ProvideResponseAsync(request);
|
||||
var responseMessage = await response.ProvideResponseAsync(request, _settingsMock.Object);
|
||||
|
||||
// Assert
|
||||
Check.That(responseMessage.BodyData.BodyAsString).IsEqualTo("{\"p\":42}");
|
||||
|
||||
@@ -1,27 +1,51 @@
|
||||
using System;
|
||||
using NFluent;
|
||||
using FluentAssertions;
|
||||
using Moq;
|
||||
using System;
|
||||
using WireMock.RequestBuilders;
|
||||
using WireMock.ResponseBuilders;
|
||||
using WireMock.Serialization;
|
||||
using WireMock.Settings;
|
||||
using Xunit;
|
||||
|
||||
namespace WireMock.Net.Tests.Serialization
|
||||
{
|
||||
public class MappingConverterTests
|
||||
{
|
||||
private readonly Mock<IFluentMockServerSettings> _settingsMock = new Mock<IFluentMockServerSettings>();
|
||||
|
||||
[Fact]
|
||||
public void MappingConverter_ToMappingModel()
|
||||
public void ToMappingModel()
|
||||
{
|
||||
// Assign
|
||||
var request = Request.Create();
|
||||
var response = Response.Create();
|
||||
var mapping = new Mapping(Guid.NewGuid(), "", null, request, response, 0, null, null, null);
|
||||
var mapping = new Mapping(Guid.NewGuid(), "", null, _settingsMock.Object, request, response, 0, null, null, null);
|
||||
|
||||
// Act
|
||||
var model = MappingConverter.ToMappingModel(mapping);
|
||||
|
||||
// Assert
|
||||
Check.That(model).IsNotNull();
|
||||
model.Should().NotBeNull();
|
||||
model.Priority.Should().BeNull();
|
||||
model.Response.BodyAsJsonIndented.Should().BeNull();
|
||||
model.Response.UseTransformer.Should().BeNull();
|
||||
}
|
||||
|
||||
[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(), "", null, _settingsMock.Object, request, response, 42, null, null, null);
|
||||
|
||||
// Act
|
||||
var model = MappingConverter.ToMappingModel(mapping);
|
||||
|
||||
// Assert
|
||||
model.Should().NotBeNull();
|
||||
model.Priority.Should().Be(42);
|
||||
model.Response.UseTransformer.Should().BeTrue();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
using System;
|
||||
using NFluent;
|
||||
using NFluent;
|
||||
using System;
|
||||
using WireMock.Admin.Mappings;
|
||||
using WireMock.Matchers;
|
||||
using WireMock.Serialization;
|
||||
@@ -53,6 +53,23 @@ namespace WireMock.Net.Tests.Serialization
|
||||
Check.That(matcher.GetPatterns()).ContainsExactly("x", "y");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MatcherModelMapper_Map_ExactObjectMatcher_Pattern()
|
||||
{
|
||||
// Assign
|
||||
var model = new MatcherModel
|
||||
{
|
||||
Name = "ExactObjectMatcher",
|
||||
Patterns = new object[] { "c3RlZg==" }
|
||||
};
|
||||
|
||||
// Act
|
||||
var matcher = (ExactObjectMatcher)MatcherMapper.Map(model);
|
||||
|
||||
// Assert
|
||||
Check.That(matcher.ValueAsBytes).ContainsExactly(new byte[] { 115, 116, 101, 102 });
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MatcherModelMapper_Map_RegexMatcher()
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Reflection;
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
namespace WireMock.Net.Tests
|
||||
{
|
||||
@@ -10,5 +11,53 @@ namespace WireMock.Net.Tests
|
||||
|
||||
return (T)field.GetValue(obj);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set a _private_ Field Value on a given Object
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Type of the Property</typeparam>
|
||||
/// <param name="obj">Object from where the Property Value is returned</param>
|
||||
/// <param name="propertyName">Property name as string.</param>
|
||||
/// <param name="value">the value to set</param>
|
||||
public static void SetPrivateFieldValue<T>(this object obj, string propertyName, T value)
|
||||
{
|
||||
if (obj == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(obj));
|
||||
}
|
||||
|
||||
Type t = obj.GetType();
|
||||
FieldInfo fi = null;
|
||||
while (fi == null && t != null)
|
||||
{
|
||||
fi = t.GetField(propertyName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
t = t.BaseType;
|
||||
}
|
||||
|
||||
if (fi == null)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(propertyName), $"Field {propertyName} was not found in Type {obj.GetType().FullName}");
|
||||
}
|
||||
|
||||
fi.SetValue(obj, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets a _private_ Property Value from a given Object.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Type of the Property</typeparam>
|
||||
/// <param name="obj">Object from where the Property Value is set</param>
|
||||
/// <param name="propertyName">Property name as string.</param>
|
||||
/// <param name="value">Value to set.</param>
|
||||
public static void SetPrivatePropertyValue<T>(this object obj, string propertyName, T value)
|
||||
{
|
||||
Type t = obj.GetType();
|
||||
if (t.GetProperty(propertyName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance) == null)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(propertyName), $"Property {propertyName} was not found in Type {obj.GetType().FullName}");
|
||||
}
|
||||
|
||||
t.InvokeMember(propertyName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.SetProperty | BindingFlags.Instance, null, obj, new object[] { value });
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user