mirror of
https://github.com/wiremock/WireMock.Net.git
synced 2026-01-11 22:30:41 +01:00
Compare commits
45 Commits
CommandLin
...
1.0.21.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 | ||
|
|
62550b61e8 | ||
|
|
d736745aff | ||
|
|
34abd05d19 | ||
|
|
f9ab43bf58 | ||
|
|
62823688a3 | ||
|
|
33f40c0e84 | ||
|
|
98097a033e | ||
|
|
d654ef97dc | ||
|
|
4be1483a5f | ||
|
|
cd200a10a4 | ||
|
|
dc36da45ec |
98
CHANGELOG.md
98
CHANGELOG.md
@@ -1,8 +1,102 @@
|
||||
# 1.0.4.21 (09 November 2018)
|
||||
# 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]
|
||||
- [#243](https://github.com/WireMock-Net/WireMock.Net/issues/243) - Not able to read response from file [question]
|
||||
|
||||
# 1.0.6.1 (10 January 2019)
|
||||
- [#247](https://github.com/WireMock-Net/WireMock.Net/pull/247) - Issue 225 improve logging in example for wire mock as windows service contributed by [paulssn](https://github.com/paulssn)
|
||||
- [#249](https://github.com/WireMock-Net/WireMock.Net/pull/249) - Fixed "Content-Type multipart/form-data" [bug] contributed by [StefH](https://github.com/StefH)
|
||||
- [#225](https://github.com/WireMock-Net/WireMock.Net/issues/225) - Feature: Improve logging in example for WireMock as Windows Service [feature]
|
||||
- [#238](https://github.com/WireMock-Net/WireMock.Net/issues/238) - Localhost and free port problem [question]
|
||||
- [#245](https://github.com/WireMock-Net/WireMock.Net/issues/245) - Not able to match XML request body using XPathMatcher pattern [question]
|
||||
- [#248](https://github.com/WireMock-Net/WireMock.Net/issues/248) - Content-Type multipart/form-data is not seen as byte[] anymore
|
||||
|
||||
# 1.0.6 (15 December 2018)
|
||||
- [#242](https://github.com/WireMock-Net/WireMock.Net/pull/242) - Post multiple Mappings [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#237](https://github.com/WireMock-Net/WireMock.Net/issues/237) - Port not released [question]
|
||||
- [#239](https://github.com/WireMock-Net/WireMock.Net/issues/239) - Not able to hit the mock server if AllowPartialMapping is not set to true [question]
|
||||
|
||||
# 1.0.5 (07 December 2018)
|
||||
- [#236](https://github.com/WireMock-Net/WireMock.Net/pull/236) - Add Random Regex (using Fare) [feature] contributed by [StefH](https://github.com/StefH)
|
||||
|
||||
# 1.0.4.21 (30 November 2018)
|
||||
- [#221](https://github.com/WireMock-Net/WireMock.Net/pull/221) - Update dependencies [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#229](https://github.com/WireMock-Net/WireMock.Net/pull/229) - Fix proxy tests [test] contributed by [StefH](https://github.com/StefH)
|
||||
- [#230](https://github.com/WireMock-Net/WireMock.Net/pull/230) - Add HandleBars Random functionality (#219) [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#231](https://github.com/WireMock-Net/WireMock.Net/pull/231) - Use RandomDataGenerator.Net 1.0.3.0 contributed by [StefH](https://github.com/StefH)
|
||||
- [#232](https://github.com/WireMock-Net/WireMock.Net/pull/232) - Add SonarLint checks [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#233](https://github.com/WireMock-Net/WireMock.Net/pull/233) - RandomDataGenerator.Net 1.0.4 [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#235](https://github.com/WireMock-Net/WireMock.Net/pull/235) - Check aggregate exception during startup [bug] contributed by [StefH](https://github.com/StefH)
|
||||
- [#219](https://github.com/WireMock-Net/WireMock.Net/issues/219) - Feature: random value helper [feature]
|
||||
- [#234](https://github.com/WireMock-Net/WireMock.Net/issues/234) - Timeout Exception on VSTS Test Platform (Azure DevOps), with private build agent
|
||||
|
||||
# 1.0.4.20 (07 November 2018)
|
||||
- [#222](https://github.com/WireMock-Net/WireMock.Net/pull/222) - Codecov contributed by [StefH](https://github.com/StefH)
|
||||
@@ -158,7 +252,7 @@
|
||||
- [#124](https://github.com/WireMock-Net/WireMock.Net/issues/124) - Issue: Unable to get host to listen on ips other than 127.0.0.1 using StandAloneApp
|
||||
|
||||
# 1.0.3.15 (05 April 2018)
|
||||
- [#117](https://github.com/WireMock-Net/WireMock.Net/pull/117) - Respect start timeout setting and expose exception from server startup contributed by [msft-eliang](https://github.com/msft-eliang)
|
||||
- [#117](https://github.com/WireMock-Net/WireMock.Net/pull/117) - Respect start timeout setting and expose exception from server startup contributed by [evanlwj](https://github.com/evanlwj)
|
||||
|
||||
# 1.0.3.14 (01 April 2018)
|
||||
- [#111](https://github.com/WireMock-Net/WireMock.Net/issues/111) - Question: Adding wiki documentation on how to use WireMock.Net.WebApplication project
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<VersionPrefix>1.0.4.20</VersionPrefix>
|
||||
<VersionPrefix>1.0.21</VersionPrefix>
|
||||
</PropertyGroup>
|
||||
|
||||
<Choose>
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
https://github.com/StefH/GitHubReleaseNotes
|
||||
|
||||
GitHubReleaseNotes.exe --output CHANGELOG.md --skip-empty-releases --version 1.0.4.21
|
||||
GitHubReleaseNotes.exe --output CHANGELOG.md --skip-empty-releases --version 1.0.21.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
|
||||
* Record/playback of stubs (proxying)
|
||||
* Per-request conditional proxying
|
||||
* Stateful behaviour simulation
|
||||
* Configurable response delays
|
||||
* 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)
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -18,6 +18,10 @@
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="__admin\mappings\array.json" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\WireMock.Net\WireMock.Net.csproj" />
|
||||
<PackageReference Include="log4net" Version="2.0.8" />
|
||||
@@ -37,6 +41,9 @@
|
||||
<None Update="__admin\mappings\791a3f31-6946-4ce7-8e6f-0237c7443275.json">
|
||||
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="__admin\mappings\MyXmlResponse.xml">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"Request": {
|
||||
"Path": {
|
||||
"Matchers": [
|
||||
{
|
||||
"Name": "WildcardMatcher",
|
||||
"Pattern": "/bodyasfilexmltest",
|
||||
"IgnoreCase": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"Methods": [
|
||||
"get"
|
||||
]
|
||||
},
|
||||
"Response": {
|
||||
"StatusCode": 200,
|
||||
"Headers": {"Content-Type": "application/xml"},
|
||||
"BodyAsFile": "MyXmlResponse.xml",
|
||||
"UseTransformer": false
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
<xml>
|
||||
<hello>world</hello>
|
||||
</xml>
|
||||
@@ -0,0 +1,46 @@
|
||||
[
|
||||
{
|
||||
"Title": "1",
|
||||
"Request": {
|
||||
"Path": {
|
||||
"Matchers": [
|
||||
{
|
||||
"Name": "WildcardMatcher",
|
||||
"Pattern": "/mappings_static_1"
|
||||
}
|
||||
]
|
||||
},
|
||||
"Methods": [
|
||||
"get"
|
||||
]
|
||||
},
|
||||
"Response": {
|
||||
"BodyAsJson": { "result": "mappings static_1" },
|
||||
"Headers": {
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"Title": "2",
|
||||
"Request": {
|
||||
"Path": {
|
||||
"Matchers": [
|
||||
{
|
||||
"Name": "WildcardMatcher",
|
||||
"Pattern": "/mappings_static_2"
|
||||
}
|
||||
]
|
||||
},
|
||||
"Methods": [
|
||||
"get"
|
||||
]
|
||||
},
|
||||
"Response": {
|
||||
"BodyAsJson": { "result": "mappings static_2" },
|
||||
"Headers": {
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -43,5 +43,51 @@ namespace WireMock.Net.ConsoleApplication
|
||||
{
|
||||
File.WriteAllText(path, text);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IFileSystemHandler.ReadResponseBodyAsFile"/>
|
||||
public byte[] ReadResponseBodyAsFile(string path)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
using System;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Net;
|
||||
using Newtonsoft.Json;
|
||||
using WireMock.Logging;
|
||||
using WireMock.Matchers;
|
||||
using WireMock.RequestBuilders;
|
||||
@@ -33,13 +33,14 @@ 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));
|
||||
|
||||
server.SetBasicAuthentication("a", "b");
|
||||
|
||||
server.AllowPartialMapping();
|
||||
// server.AllowPartialMapping();
|
||||
|
||||
server
|
||||
.Given(Request.Create().WithPath(p => p.Contains("x")).UsingGet())
|
||||
@@ -388,11 +389,10 @@ namespace WireMock.Net.ConsoleApplication
|
||||
.WithStatusCode(500)
|
||||
.WithBody(requestMessage =>
|
||||
{
|
||||
string returnStr = JsonConvert.SerializeObject(new
|
||||
return JsonConvert.SerializeObject(new
|
||||
{
|
||||
Message = "Test error"
|
||||
});
|
||||
return returnStr;
|
||||
})
|
||||
);
|
||||
|
||||
@@ -402,26 +402,52 @@ namespace WireMock.Net.ConsoleApplication
|
||||
.WithHeader("Content-Type", "application/json")
|
||||
.WithBodyAsJson(new
|
||||
{
|
||||
Xeger1 = "{{Xeger \"\\w{4}\\d{5}\"}}",
|
||||
Xeger2 = "{{Xeger \"\\d{5}\"}}",
|
||||
TextRegexPostcode = "{{Random Type=\"TextRegex\" Pattern=\"[1-9][0-9]{3}[A-Z]{2}\"}}",
|
||||
Text = "{{Random Type=\"Text\" Min=8 Max=20}}",
|
||||
TextLipsum = "{{Random Type=\"TextLipsum\"}}",
|
||||
IBAN = "{{Random Type=\"IBAN\" CountryCode=\"NL\"}}",
|
||||
TimeSpan1 = "{{Random Type=\"TimeSpan\" Format=\"c\" IncludeMilliseconds=false}}",
|
||||
TimeSpan2 = "{{Random Type=\"TimeSpan\"}}",
|
||||
DateTime1 = "{{Random Type=\"DateTime\"}}",
|
||||
DateTimeNow = DateTime.Now,
|
||||
DateTimeToString = DateTime.Now.ToString("s", CultureInfo.InvariantCulture),
|
||||
DateTimeNowToString = DateTime.Now.ToString("s", CultureInfo.InvariantCulture),
|
||||
Guid1 = "{{Random Type=\"Guid\" Uppercase=false}}",
|
||||
Guid2 = "{{Random Type=\"Guid\"}}",
|
||||
Integer1 = "{{Random Type=\"Integer\" Min=1000 Max=9999}}",
|
||||
Integer2 = "{{#Random Type=\"Integer\" Min=10000000 Max=99999999}}{{this}}{{/Random}}",
|
||||
Double1 = "{{Random Type=\"Double\" Min=10 Max=99}}",
|
||||
Double2 = "{{Random Type=\"Double\" Min=100 Max=999}}",
|
||||
Boolean = "{{Random Type=\"Boolean\"}}",
|
||||
Integer = "{{Random Type=\"Integer\" Min=1000 Max=9999}}",
|
||||
Long = "{{#Random Type=\"Long\" Min=10000000 Max=99999999}}{{this}}{{/Random}}",
|
||||
Double = "{{Random Type=\"Double\" Min=10 Max=99}}",
|
||||
Float = "{{Random Type=\"Float\" Min=100 Max=999}}",
|
||||
IP4Address = "{{Random Type=\"IPv4Address\" Min=\"10.2.3.4\"}}",
|
||||
IP6Address = "{{Random Type=\"IPv6Address\"}}",
|
||||
MACAddress = "{{Random Type=\"MACAddress\" Separator=\"-\"}}"
|
||||
MACAddress = "{{Random Type=\"MACAddress\" Separator=\"-\"}}",
|
||||
StringListValue = "{{Random Type=\"StringList\" Values=[\"a\", \"b\", \"c\"]}}"
|
||||
})
|
||||
.WithTransformer()
|
||||
);
|
||||
|
||||
server
|
||||
.Given(Request.Create()
|
||||
.UsingPost()
|
||||
.WithPath("/xpathsoap")
|
||||
.WithBody(new XPathMatcher("//*[local-name() = 'getMyData']"))
|
||||
)
|
||||
.RespondWith(Response.Create()
|
||||
.WithHeader("Content-Type", "application/xml")
|
||||
.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("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();
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
using System;
|
||||
using log4net.Config;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.ServiceProcess;
|
||||
using WireMock.Logging;
|
||||
using WireMock.Net.Service;
|
||||
using WireMock.Net.StandAlone;
|
||||
using WireMock.Server;
|
||||
using WireMock.Settings;
|
||||
@@ -21,7 +23,7 @@ namespace Wiremock.Net.Service
|
||||
|
||||
protected override void OnStart(string[] args)
|
||||
{
|
||||
Start(new WireMockNullLogger());
|
||||
Start();
|
||||
}
|
||||
|
||||
protected override void OnStop()
|
||||
@@ -35,6 +37,11 @@ namespace Wiremock.Net.Service
|
||||
|
||||
static void Main(string[] args)
|
||||
{
|
||||
//Setting the current directory explicitly is required if the application is running as Windows Service,
|
||||
//as the current directory of a Windows Service is %WinDir%\System32 per default.
|
||||
Directory.SetCurrentDirectory(AppDomain.CurrentDomain.BaseDirectory);
|
||||
XmlConfigurator.ConfigureAndWatch(new FileInfo("log4net.config"));
|
||||
|
||||
// running as service
|
||||
if (!Environment.UserInteractive)
|
||||
{
|
||||
@@ -46,7 +53,7 @@ namespace Wiremock.Net.Service
|
||||
else
|
||||
{
|
||||
// running as console app
|
||||
Start(new WireMockConsoleLogger());
|
||||
Start();
|
||||
|
||||
Console.WriteLine("Press any key to stop...");
|
||||
Console.ReadKey(true);
|
||||
@@ -55,14 +62,14 @@ namespace Wiremock.Net.Service
|
||||
}
|
||||
}
|
||||
|
||||
private static void Start(IWireMockLogger logger)
|
||||
private static void Start()
|
||||
{
|
||||
_server = StandAloneApp.Start(new FluentMockServerSettings
|
||||
{
|
||||
Urls = new[] { "http://*:9091/" },
|
||||
StartAdminInterface = true,
|
||||
ReadStaticMappings = true,
|
||||
Logger = logger
|
||||
Logger = new WireMockLog4NetLogger()
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -35,6 +35,9 @@
|
||||
<Reference Include="Handlebars, Version=1.9.5.0, Culture=neutral, PublicKeyToken=22225d0bf33cd661, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Handlebars.Net.1.9.5\lib\net452\Handlebars.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="log4net, Version=2.0.8.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\log4net.2.0.8\lib\net45-full\log4net.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Owin, Version=2.0.2.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Microsoft.Owin.2.0.2\lib\net45\Microsoft.Owin.dll</HintPath>
|
||||
</Reference>
|
||||
@@ -96,9 +99,13 @@
|
||||
</Compile>
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="WireMockLog4NetLogger.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
<None Include="log4net.config">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="Service-Start.bat">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
|
||||
39
examples/WireMock.Net.Service/WireMockLog4NetLogger.cs
Normal file
39
examples/WireMock.Net.Service/WireMockLog4NetLogger.cs
Normal file
@@ -0,0 +1,39 @@
|
||||
using log4net;
|
||||
using Newtonsoft.Json;
|
||||
using Wiremock.Net.Service;
|
||||
using WireMock.Admin.Requests;
|
||||
using WireMock.Logging;
|
||||
|
||||
namespace WireMock.Net.Service
|
||||
{
|
||||
internal class WireMockLog4NetLogger : IWireMockLogger
|
||||
{
|
||||
private static readonly ILog Log = LogManager.GetLogger(typeof(Program));
|
||||
|
||||
public void Debug(string formatString, params object[] args)
|
||||
{
|
||||
Log.DebugFormat(formatString, args);
|
||||
}
|
||||
|
||||
public void Info(string formatString, params object[] args)
|
||||
{
|
||||
Log.InfoFormat(formatString, args);
|
||||
}
|
||||
|
||||
public void Warn(string formatString, params object[] args)
|
||||
{
|
||||
Log.WarnFormat(formatString, args);
|
||||
}
|
||||
|
||||
public void Error(string formatString, params object[] args)
|
||||
{
|
||||
Log.ErrorFormat(formatString, args);
|
||||
}
|
||||
|
||||
public void DebugRequestResponse(LogEntryModel logEntryModel, bool isAdminRequest)
|
||||
{
|
||||
string message = JsonConvert.SerializeObject(logEntryModel, Formatting.Indented);
|
||||
Log.DebugFormat("Admin[{0}] {1}", isAdminRequest, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
38
examples/WireMock.Net.Service/log4net.config
Normal file
38
examples/WireMock.Net.Service/log4net.config
Normal file
@@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<configuration>
|
||||
<configSections>
|
||||
<section name="log4net" type="System.Configuration.IgnoreSectionHandler" />
|
||||
</configSections>
|
||||
<appSettings>
|
||||
<add key="log4net.Internal.Debug" value="true"/>
|
||||
</appSettings>
|
||||
<log4net>
|
||||
<appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
|
||||
<layout type="log4net.Layout.PatternLayout">
|
||||
<conversionPattern value="%date [%thread] %-5level %logger{1} - %message%newline" />
|
||||
</layout>
|
||||
</appender>
|
||||
<appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
|
||||
<file value="log.txt" />
|
||||
<appendToFile value="true" />
|
||||
<rollingStyle value="Size" />
|
||||
<maxSizeRollBackups value="10" />
|
||||
<maximumFileSize value="10000KB" />
|
||||
<staticLogFileName value="true" />
|
||||
<layout type="log4net.Layout.PatternLayout">
|
||||
<conversionPattern value="%date [%thread] %-5level %logger{1} - %message%newline" />
|
||||
</layout>
|
||||
</appender>
|
||||
<appender name="EventLogAppender" type="log4net.Appender.EventLogAppender" >
|
||||
<layout type="log4net.Layout.PatternLayout">
|
||||
<conversionPattern value="%date [%thread] %-5level %logger{1} - %message%newline" />
|
||||
</layout>
|
||||
</appender>
|
||||
<root>
|
||||
<level value="DEBUG" />
|
||||
<appender-ref ref="ConsoleAppender" />
|
||||
<appender-ref ref="RollingLogFileAppender" />
|
||||
<!--<appender-ref ref="EventLogAppender" /> --> <!-- comment in if needed -->
|
||||
</root>
|
||||
</log4net>
|
||||
</configuration>
|
||||
@@ -1,6 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Handlebars.Net" version="1.9.5" targetFramework="net452" />
|
||||
<package id="log4net" version="2.0.8" targetFramework="net452" />
|
||||
<package id="Microsoft.AspNet.WebApi.Client" version="5.2.3" targetFramework="net452" />
|
||||
<package id="Microsoft.AspNet.WebApi.Core" version="5.2.3" targetFramework="net452" />
|
||||
<package id="Microsoft.AspNet.WebApi.Owin" version="5.2.3" targetFramework="net452" />
|
||||
|
||||
@@ -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' ">
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -58,6 +58,14 @@ namespace WireMock.Client
|
||||
[Header("Content-Type", "application/json")]
|
||||
Task<StatusModel> PostMappingAsync([Body] MappingModel mapping);
|
||||
|
||||
/// <summary>
|
||||
/// Add new mappings.
|
||||
/// </summary>
|
||||
/// <param name="mappings">MappingModels</param>
|
||||
[Post("__admin/mappings")]
|
||||
[Header("Content-Type", "application/json")]
|
||||
Task<StatusModel> PostMappingsAsync([Body] IList<MappingModel> mappings);
|
||||
|
||||
/// <summary>
|
||||
/// Delete all mappings.
|
||||
/// </summary>
|
||||
@@ -159,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);
|
||||
}
|
||||
}
|
||||
35
src/WireMock.Net/Exceptions/WireMockException.cs
Normal file
35
src/WireMock.Net/Exceptions/WireMockException.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using System;
|
||||
|
||||
namespace WireMock.Exceptions
|
||||
{
|
||||
/// <summary>
|
||||
/// WireMockException
|
||||
/// </summary>
|
||||
/// <seealso cref="Exception" />
|
||||
public class WireMockException : Exception
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="WireMockException"/> class.
|
||||
/// </summary>
|
||||
public WireMockException()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="WireMockException"/> class.
|
||||
/// </summary>
|
||||
/// <param name="message">The message that describes the error.</param>
|
||||
public WireMockException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="WireMockException"/> class.
|
||||
/// </summary>
|
||||
/// <param name="message">The message.</param>
|
||||
/// <param name="inner">The inner.</param>
|
||||
public WireMockException(string message, Exception inner) : base(message, inner)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using JetBrains.Annotations;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace WireMock.Handlers
|
||||
{
|
||||
@@ -10,7 +11,7 @@ namespace WireMock.Handlers
|
||||
/// <summary>
|
||||
/// Gets the folder where the static mappings are located. For local file system, this would be `{CurrentFolder}/__admin/mappings`.
|
||||
/// </summary>
|
||||
/// <returns>The foldername.</returns>
|
||||
/// <returns>The folder name.</returns>
|
||||
string GetMappingFolder();
|
||||
|
||||
/// <summary>
|
||||
@@ -18,32 +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>
|
||||
string ReadMappingFile(string path);
|
||||
/// <returns>The file content as text.</returns>
|
||||
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[] ReadFile([NotNull] string filename);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using JetBrains.Annotations;
|
||||
using WireMock.Validation;
|
||||
|
||||
namespace WireMock.Handlers
|
||||
@@ -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,24 +56,87 @@ 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));
|
||||
|
||||
File.WriteAllText(path, text);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IFileSystemHandler.ReadResponseBodyAsFile"/>
|
||||
public byte[] ReadResponseBodyAsFile(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.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,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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ using JetBrains.Annotations;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using WireMock.Handlers;
|
||||
using WireMock.HttpsCertificate;
|
||||
using WireMock.Logging;
|
||||
using WireMock.Owin.Mappers;
|
||||
@@ -55,10 +56,22 @@ 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<IWireMockMiddlewareOptions>(_options);
|
||||
services.AddSingleton(_options.FileSystemHandler);
|
||||
services.AddSingleton(_options);
|
||||
services.AddSingleton<IMappingMatcher, MappingMatcher>();
|
||||
services.AddSingleton<IOwinRequestMapper, OwinRequestMapper>();
|
||||
services.AddSingleton<IOwinResponseMapper, OwinResponseMapper>();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.ObjectModel;
|
||||
using WireMock.Handlers;
|
||||
using WireMock.Logging;
|
||||
using WireMock.Matchers;
|
||||
#if !USE_ASPNETCORE
|
||||
@@ -34,5 +35,7 @@ namespace WireMock.Owin
|
||||
Action<IAppBuilder> PreWireMockMiddlewareInit { get; set; }
|
||||
|
||||
Action<IAppBuilder> PostWireMockMiddlewareInit { get; set; }
|
||||
|
||||
IFileSystemHandler FileSystemHandler { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
using WireMock.Handlers;
|
||||
using WireMock.Http;
|
||||
using WireMock.Util;
|
||||
using WireMock.Validation;
|
||||
#if !USE_ASPNETCORE
|
||||
using IResponse = Microsoft.Owin.IOwinResponse;
|
||||
#else
|
||||
@@ -21,6 +22,7 @@ namespace WireMock.Owin.Mappers
|
||||
/// </summary>
|
||||
public class OwinResponseMapper : IOwinResponseMapper
|
||||
{
|
||||
private readonly IFileSystemHandler _fileSystemHandler;
|
||||
private readonly Encoding _utf8NoBom = new UTF8Encoding(false);
|
||||
|
||||
// https://msdn.microsoft.com/en-us/library/78h415ay(v=vs.110).aspx
|
||||
@@ -32,6 +34,17 @@ namespace WireMock.Owin.Mappers
|
||||
{ HttpKnownHeaderNames.ContentType, (r, v) => r.ContentType = v.FirstOrDefault() }
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="fileSystemHandler">The IFileSystemHandler.</param>
|
||||
public OwinResponseMapper(IFileSystemHandler fileSystemHandler)
|
||||
{
|
||||
Check.NotNull(fileSystemHandler, nameof(fileSystemHandler));
|
||||
|
||||
_fileSystemHandler = fileSystemHandler;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IOwinResponseMapper.MapAsync"/>
|
||||
public async Task MapAsync(ResponseMessage responseMessage, IResponse response)
|
||||
{
|
||||
@@ -60,7 +73,7 @@ namespace WireMock.Owin.Mappers
|
||||
break;
|
||||
|
||||
case BodyType.File:
|
||||
bytes = File.ReadAllBytes(responseMessage.BodyData.BodyAsFile);
|
||||
bytes = _fileSystemHandler.ReadResponseBodyAsFile(responseMessage.BodyData.BodyAsFile);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using WireMock.Handlers;
|
||||
using WireMock.Logging;
|
||||
using WireMock.Owin.Mappers;
|
||||
using WireMock.Util;
|
||||
@@ -75,7 +76,7 @@ namespace WireMock.Owin
|
||||
try
|
||||
{
|
||||
var requestMapper = new OwinRequestMapper();
|
||||
var responseMapper = new OwinResponseMapper();
|
||||
var responseMapper = new OwinResponseMapper(_options.FileSystemHandler);
|
||||
var matcher = new MappingMatcher(_options);
|
||||
|
||||
Action<IAppBuilder> startup = app =>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.ObjectModel;
|
||||
using WireMock.Handlers;
|
||||
using WireMock.Logging;
|
||||
using WireMock.Matchers;
|
||||
using WireMock.Util;
|
||||
@@ -35,5 +36,8 @@ namespace WireMock.Owin
|
||||
public Action<IAppBuilder> PreWireMockMiddlewareInit { get; set; }
|
||||
|
||||
public Action<IAppBuilder> PostWireMockMiddlewareInit { get; set; }
|
||||
|
||||
/// <inheritdoc cref="IWireMockMiddlewareOptions.FileSystemHandler"/>
|
||||
public IFileSystemHandler FileSystemHandler { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -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,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>
|
||||
|
||||
90
src/WireMock.Net/RequestBuilders/Request.Params.cs
Normal file
90
src/WireMock.Net/RequestBuilders/Request.Params.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;
|
||||
|
||||
@@ -291,54 +290,6 @@ namespace WireMock.RequestBuilders
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,14 @@
|
||||
using JetBrains.Annotations;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using JetBrains.Annotations;
|
||||
using Newtonsoft.Json;
|
||||
using WireMock.Http;
|
||||
using WireMock.ResponseProviders;
|
||||
using WireMock.Settings;
|
||||
using WireMock.Transformers;
|
||||
using WireMock.Util;
|
||||
@@ -220,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 = File.ReadAllBytes(filename);
|
||||
}
|
||||
else
|
||||
{
|
||||
ResponseMessage.BodyData.DetectedBodyType = BodyType.File;
|
||||
ResponseMessage.BodyData.BodyAsFile = filename;
|
||||
}
|
||||
|
||||
return this;
|
||||
@@ -255,7 +254,7 @@ namespace WireMock.ResponseBuilders
|
||||
{
|
||||
case BodyDestinationFormat.Bytes:
|
||||
ResponseMessage.BodyData.DetectedBodyType = BodyType.Bytes;
|
||||
ResponseMessage.BodyData.BodyAsBytes= encoding.GetBytes(body);
|
||||
ResponseMessage.BodyData.BodyAsBytes = encoding.GetBytes(body);
|
||||
break;
|
||||
|
||||
case BodyDestinationFormat.Json:
|
||||
@@ -285,7 +284,7 @@ namespace WireMock.ResponseBuilders
|
||||
BodyAsJson = body,
|
||||
BodyAsJsonIndented = indented
|
||||
};
|
||||
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -372,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));
|
||||
|
||||
@@ -416,10 +411,17 @@ 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);
|
||||
ResponseMessage.BodyData.BodyAsFile = null;
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace WireMock.Serialization
|
||||
{
|
||||
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,6 +66,7 @@ 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,
|
||||
|
||||
@@ -76,7 +77,7 @@ namespace WireMock.Serialization
|
||||
},
|
||||
Response = new ResponseModel
|
||||
{
|
||||
Delay = response.Delay?.Milliseconds
|
||||
Delay = (int?)response.Delay?.TotalMilliseconds
|
||||
}
|
||||
};
|
||||
|
||||
@@ -91,7 +92,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 +101,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 +116,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;
|
||||
|
||||
@@ -32,6 +32,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 +45,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);
|
||||
|
||||
@@ -73,20 +80,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
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
using JetBrains.Annotations;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
@@ -5,9 +8,6 @@ using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using JetBrains.Annotations;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using WireMock.Admin.Mappings;
|
||||
using WireMock.Admin.Scenarios;
|
||||
using WireMock.Admin.Settings;
|
||||
@@ -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>
|
||||
@@ -156,10 +164,10 @@ namespace WireMock.Server
|
||||
{
|
||||
if (folder == null)
|
||||
{
|
||||
folder = _fileSystemHandler.GetMappingFolder();
|
||||
folder = _settings.FileSystemHandler.GetMappingFolder();
|
||||
}
|
||||
|
||||
if (!_fileSystemHandler.FolderExists(folder))
|
||||
if (!_settings.FileSystemHandler.FolderExists(folder))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -169,17 +177,23 @@ namespace WireMock.Server
|
||||
var watcher = new EnhancedFileSystemWatcher(folder, "*.json", EnhancedFileSystemWatcherTimeoutMs);
|
||||
watcher.Created += (sender, args) =>
|
||||
{
|
||||
_logger.Info("New MappingFile created : '{0}'", args.FullPath);
|
||||
ReadStaticMappingAndAddOrUpdate(args.FullPath);
|
||||
_logger.Info("MappingFile created : '{0}', reading file.", args.FullPath);
|
||||
if (!ReadStaticMappingAndAddOrUpdate(args.FullPath))
|
||||
{
|
||||
_logger.Error("Unable to read MappingFile '{0}'.", args.FullPath);
|
||||
}
|
||||
};
|
||||
watcher.Changed += (sender, args) =>
|
||||
{
|
||||
_logger.Info("New MappingFile updated : '{0}'", args.FullPath);
|
||||
ReadStaticMappingAndAddOrUpdate(args.FullPath);
|
||||
_logger.Info("MappingFile updated : '{0}', reading file.", args.FullPath);
|
||||
if (!ReadStaticMappingAndAddOrUpdate(args.FullPath))
|
||||
{
|
||||
_logger.Error("Unable to read MappingFile '{0}'.", args.FullPath);
|
||||
}
|
||||
};
|
||||
watcher.Deleted += (sender, args) =>
|
||||
{
|
||||
_logger.Info("New MappingFile deleted : '{0}'", args.FullPath);
|
||||
_logger.Info("MappingFile deleted : '{0}'", args.FullPath);
|
||||
string filenameWithoutExtension = Path.GetFileNameWithoutExtension(args.FullPath);
|
||||
|
||||
if (Guid.TryParse(filenameWithoutExtension, out Guid guidFromFilename))
|
||||
@@ -200,21 +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);
|
||||
|
||||
MappingModel mappingModel = JsonConvert.DeserializeObject<MappingModel>(_fileSystemHandler.ReadMappingFile(path));
|
||||
if (Guid.TryParse(filenameWithoutExtension, out Guid guidFromFilename))
|
||||
if (FileHelper.TryReadMappingFileWithRetryAndDelay(_fileSystemHandler, path, out string value))
|
||||
{
|
||||
DeserializeAndAddOrUpdateMapping(mappingModel, guidFromFilename, path);
|
||||
}
|
||||
else
|
||||
{
|
||||
DeserializeAndAddOrUpdateMapping(mappingModel, null, path);
|
||||
var mappingModels = DeserializeObjectToArray<MappingModel>(JsonConvert.DeserializeObject(value));
|
||||
foreach (var mappingModel in mappingModels)
|
||||
{
|
||||
if (mappingModels.Length == 1 && Guid.TryParse(filenameWithoutExtension, out Guid guidFromFilename))
|
||||
{
|
||||
DeserializeAndAddOrUpdateMapping(mappingModel, guidFromFilename, path);
|
||||
}
|
||||
else
|
||||
{
|
||||
DeserializeAndAddOrUpdateMapping(mappingModel, null, path);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
#endregion
|
||||
|
||||
@@ -231,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);
|
||||
}
|
||||
@@ -262,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" };
|
||||
@@ -274,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
|
||||
|
||||
@@ -390,7 +420,7 @@ namespace WireMock.Server
|
||||
|
||||
_logger.Info("Saving Mapping file {0}", filename);
|
||||
|
||||
_fileSystemHandler.WriteMappingFile(path, JsonConvert.SerializeObject(model, _settings));
|
||||
_fileSystemHandler.WriteMappingFile(path, JsonConvert.SerializeObject(model, _jsonSerializerSettings));
|
||||
}
|
||||
|
||||
private static string SanitizeFileName(string name, char replaceChar = '_')
|
||||
@@ -412,11 +442,21 @@ namespace WireMock.Server
|
||||
|
||||
private ResponseMessage MappingsPost(RequestMessage requestMessage)
|
||||
{
|
||||
Guid? guid;
|
||||
try
|
||||
{
|
||||
var mappingModel = DeserializeObject<MappingModel>(requestMessage);
|
||||
guid = DeserializeAndAddOrUpdateMapping(mappingModel);
|
||||
var mappingModels = DeserializeRequestMessageToArray<MappingModel>(requestMessage);
|
||||
if (mappingModels.Length == 1)
|
||||
{
|
||||
Guid? guid = DeserializeAndAddOrUpdateMapping(mappingModels[0]);
|
||||
return ResponseMessageBuilder.Create("Mapping added", 201, guid);
|
||||
}
|
||||
|
||||
foreach (var mappingModel in mappingModels)
|
||||
{
|
||||
DeserializeAndAddOrUpdateMapping(mappingModel);
|
||||
}
|
||||
|
||||
return ResponseMessageBuilder.Create("Mappings added", 201);
|
||||
}
|
||||
catch (ArgumentException a)
|
||||
{
|
||||
@@ -428,8 +468,6 @@ namespace WireMock.Server
|
||||
_logger.Error("HttpStatusCode set to 500 {0}", e);
|
||||
return ResponseMessageBuilder.Create(e.ToString(), 500);
|
||||
}
|
||||
|
||||
return ResponseMessageBuilder.Create("Mapping added", 201, guid);
|
||||
}
|
||||
|
||||
private Guid? DeserializeAndAddOrUpdateMapping(MappingModel mappingModel, Guid? guid = null, string path = null)
|
||||
@@ -446,7 +484,7 @@ namespace WireMock.Server
|
||||
|
||||
var responseBuilder = InitResponseBuilder(mappingModel.Response);
|
||||
|
||||
var respondProvider = Given(requestBuilder);
|
||||
var respondProvider = Given(requestBuilder, mappingModel.SaveToFile == true);
|
||||
|
||||
if (guid != null)
|
||||
{
|
||||
@@ -674,7 +712,8 @@ 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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -696,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))
|
||||
@@ -752,11 +796,6 @@ namespace WireMock.Server
|
||||
responseBuilder = responseBuilder.WithBodyFromFile(responseModel.BodyAsFile);
|
||||
}
|
||||
|
||||
if (responseModel.UseTransformer)
|
||||
{
|
||||
responseBuilder = responseBuilder.WithTransformer();
|
||||
}
|
||||
|
||||
return responseBuilder;
|
||||
}
|
||||
|
||||
@@ -767,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) } }
|
||||
@@ -793,5 +832,28 @@ namespace WireMock.Server
|
||||
|
||||
return default(T);
|
||||
}
|
||||
|
||||
private T[] DeserializeRequestMessageToArray<T>(RequestMessage requestMessage)
|
||||
{
|
||||
if (requestMessage?.BodyData?.DetectedBodyType == BodyType.Json)
|
||||
{
|
||||
var bodyAsJson = requestMessage.BodyData.BodyAsJson;
|
||||
|
||||
return DeserializeObjectToArray<T>(bodyAsJson);
|
||||
}
|
||||
|
||||
return default(T[]);
|
||||
}
|
||||
|
||||
private T[] DeserializeObjectToArray<T>(object value)
|
||||
{
|
||||
if (value is JArray jArray)
|
||||
{
|
||||
return jArray.ToObject<T[]>();
|
||||
}
|
||||
|
||||
var singleResult = ((JObject)value).ToObject<T>();
|
||||
return new[] { singleResult };
|
||||
}
|
||||
}
|
||||
}
|
||||
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 = _fileSystemHandler.GetMappingFolder();
|
||||
if (!_fileSystemHandler.FolderExists(mappingFolder))
|
||||
{
|
||||
_fileSystemHandler.CreateFolder(mappingFolder);
|
||||
}
|
||||
|
||||
_fileSystemHandler.WriteFile(filename, requestMessage.BodyAsBytes);
|
||||
|
||||
return ResponseMessageBuilder.Create("File created");
|
||||
}
|
||||
|
||||
private ResponseMessage FilePut(RequestMessage requestMessage)
|
||||
{
|
||||
string filename = GetFileNameFromRequestMessage(requestMessage);
|
||||
|
||||
if (!_fileSystemHandler.FileExists(filename))
|
||||
{
|
||||
_logger.Info("The file '{0}' does not exist, updating file will be skipped.", filename);
|
||||
return ResponseMessageBuilder.Create("File is not found", 404);
|
||||
}
|
||||
|
||||
_fileSystemHandler.WriteFile(filename, requestMessage.BodyAsBytes);
|
||||
|
||||
return ResponseMessageBuilder.Create("File updated");
|
||||
}
|
||||
|
||||
private ResponseMessage FileGet(RequestMessage requestMessage)
|
||||
{
|
||||
string filename = GetFileNameFromRequestMessage(requestMessage);
|
||||
|
||||
if (!_fileSystemHandler.FileExists(filename))
|
||||
{
|
||||
_logger.Info("The file '{0}' does not exist.", filename);
|
||||
return ResponseMessageBuilder.Create("File is not found", 404);
|
||||
}
|
||||
|
||||
byte[] bytes = _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 (!_fileSystemHandler.FileExists(filename))
|
||||
{
|
||||
_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 (!_fileSystemHandler.FileExists(filename))
|
||||
{
|
||||
_logger.Info("The file '{0}' does not exist.", filename);
|
||||
return ResponseMessageBuilder.Create("File is not deleted", 404);
|
||||
}
|
||||
|
||||
_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.Exceptions;
|
||||
using WireMock.Handlers;
|
||||
using WireMock.Logging;
|
||||
using WireMock.Matchers;
|
||||
@@ -28,6 +29,7 @@ namespace WireMock.Server
|
||||
|
||||
private readonly IWireMockLogger _logger;
|
||||
private readonly IFileSystemHandler _fileSystemHandler;
|
||||
private readonly IFluentMockServerSettings _settings;
|
||||
private readonly IOwinSelfHost _httpServer;
|
||||
private readonly IWireMockMiddlewareOptions _options = new WireMockMiddlewareOptions();
|
||||
|
||||
@@ -91,7 +93,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));
|
||||
|
||||
@@ -184,7 +186,8 @@ namespace WireMock.Server
|
||||
|
||||
private FluentMockServer(IFluentMockServerSettings settings)
|
||||
{
|
||||
settings.Logger = settings.Logger ?? new WireMockConsoleLogger();
|
||||
_settings = settings;
|
||||
settings.Logger = settings.Logger ?? new WireMockNullLogger();
|
||||
|
||||
_logger = settings.Logger;
|
||||
_fileSystemHandler = settings.FileSystemHandler ?? new LocalFileSystemHandler();
|
||||
@@ -202,6 +205,7 @@ namespace WireMock.Server
|
||||
Urls = new[] { $"{(settings.UseSSL == true ? "https" : "http")}://localhost:{port}" };
|
||||
}
|
||||
|
||||
_options.FileSystemHandler = _fileSystemHandler;
|
||||
_options.PreWireMockMiddlewareInit = settings.PreWireMockMiddlewareInit;
|
||||
_options.PostWireMockMiddlewareInit = settings.PostWireMockMiddlewareInit;
|
||||
_options.Logger = _logger;
|
||||
@@ -213,21 +217,27 @@ namespace WireMock.Server
|
||||
#endif
|
||||
Ports = _httpServer.Ports;
|
||||
|
||||
_httpServer.StartAsync();
|
||||
var startTask = _httpServer.StartAsync();
|
||||
|
||||
using (var ctsStartTimeout = new CancellationTokenSource(settings.StartTimeout))
|
||||
{
|
||||
while (!_httpServer.IsStarted)
|
||||
{
|
||||
// Throw out exception if service start fails
|
||||
// Throw exception if service start fails
|
||||
if (_httpServer.RunningException != null)
|
||||
{
|
||||
throw new Exception($"Service start failed with error: {_httpServer.RunningException.Message}", _httpServer.RunningException);
|
||||
throw new WireMockException($"Service start failed with error: {_httpServer.RunningException.Message}", _httpServer.RunningException);
|
||||
}
|
||||
|
||||
// Respect start timeout setting by throwing TimeoutException
|
||||
if (ctsStartTimeout.IsCancellationRequested)
|
||||
{
|
||||
// In case of an aggregate exception, throw the exception.
|
||||
if (startTask.Exception != null)
|
||||
{
|
||||
throw new WireMockException($"Service start failed with error: {startTask.Exception.Message}", startTask.Exception);
|
||||
}
|
||||
|
||||
// Else throw TimeoutException
|
||||
throw new TimeoutException($"Service start timed out after {TimeSpan.FromMilliseconds(settings.StartTimeout)}");
|
||||
}
|
||||
|
||||
@@ -422,14 +432,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))
|
||||
@@ -440,6 +451,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);
|
||||
|
||||
@@ -13,6 +14,10 @@ namespace WireMock.Transformers
|
||||
HandleBarsLinq.Register(handlebarsContext);
|
||||
|
||||
HandleBarsRandom.Register(handlebarsContext);
|
||||
|
||||
HandleBarsXeger.Register(handlebarsContext);
|
||||
|
||||
HandleBarsFile.Register(handlebarsContext, fileSystemHandler);
|
||||
}
|
||||
}
|
||||
}
|
||||
39
src/WireMock.Net/Transformers/HandleBarsXeger.cs
Normal file
39
src/WireMock.Net/Transformers/HandleBarsXeger.cs
Normal file
@@ -0,0 +1,39 @@
|
||||
using System;
|
||||
using Fare;
|
||||
using HandlebarsDotNet;
|
||||
using WireMock.Validation;
|
||||
|
||||
namespace WireMock.Transformers
|
||||
{
|
||||
internal static class HandleBarsXeger
|
||||
{
|
||||
public static void Register(IHandlebars handlebarsContext)
|
||||
{
|
||||
handlebarsContext.RegisterHelper("Xeger", (writer, context, arguments) =>
|
||||
{
|
||||
string value = ParseArgumentAndGenerate(arguments);
|
||||
writer.Write(value);
|
||||
});
|
||||
|
||||
handlebarsContext.RegisterHelper("Xeger", (writer, options, context, arguments) =>
|
||||
{
|
||||
string value = ParseArgumentAndGenerate(arguments);
|
||||
options.Template(writer, value);
|
||||
});
|
||||
}
|
||||
|
||||
private static string ParseArgumentAndGenerate(object[] arguments)
|
||||
{
|
||||
Check.Condition(arguments, args => args.Length == 1, nameof(arguments));
|
||||
Check.NotNull(arguments[0], "arguments[0]");
|
||||
|
||||
switch (arguments[0])
|
||||
{
|
||||
case string pattern:
|
||||
return new Xeger(pattern).Generate();
|
||||
}
|
||||
|
||||
throw new NotSupportedException($"The value '{arguments[0]}' with type '{arguments[0]?.GetType()}' cannot be used in Handlebars Xeger.");
|
||||
}
|
||||
}
|
||||
}
|
||||
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,37 +118,60 @@ 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))
|
||||
{
|
||||
JToken value;
|
||||
try
|
||||
{
|
||||
// Try to convert this string into a real JsonObject
|
||||
value = JToken.Parse(transformedString);
|
||||
}
|
||||
catch (JsonException)
|
||||
{
|
||||
// Ignore JsonException and just convert to JToken
|
||||
value = transformedString;
|
||||
}
|
||||
|
||||
node.Replace(value);
|
||||
ReplaceNodeValue(node, transformedString);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void TransformBodyAsString(object template, ResponseMessage original, ResponseMessage responseMessage)
|
||||
private static void ReplaceNodeValue(JToken node, string stringValue)
|
||||
{
|
||||
var templateBody = HandlebarsContext.Compile(original.BodyData.BodyAsString);
|
||||
if (bool.TryParse(stringValue, out bool valueAsBoolean))
|
||||
{
|
||||
node.Replace(valueAsBoolean);
|
||||
return;
|
||||
}
|
||||
|
||||
JToken value;
|
||||
try
|
||||
{
|
||||
// Try to convert this string into a JsonObject
|
||||
value = JToken.Parse(stringValue);
|
||||
}
|
||||
catch (JsonException)
|
||||
{
|
||||
// Ignore JsonException and just keep string value and convert to JToken
|
||||
value = stringValue;
|
||||
}
|
||||
|
||||
node.Replace(value);
|
||||
}
|
||||
|
||||
private static void TransformBodyAsString(IHandlebars handlebarsContext, object template, ResponseMessage original, ResponseMessage responseMessage)
|
||||
{
|
||||
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)
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
using System;
|
||||
using JetBrains.Annotations;
|
||||
using MimeKit;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using JetBrains.Annotations;
|
||||
using MimeKit;
|
||||
using Newtonsoft.Json;
|
||||
using WireMock.Matchers;
|
||||
using WireMock.Validation;
|
||||
|
||||
@@ -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,22 @@ 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)
|
||||
};
|
||||
|
||||
private static readonly IStringMatcher[] JsonContentTypesMatchers = {
|
||||
new WildcardMatcher("application/json", true),
|
||||
@@ -48,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)
|
||||
@@ -68,6 +97,11 @@ namespace WireMock.Util
|
||||
return BodyType.Json;
|
||||
}
|
||||
|
||||
if (MultipartContentTypesMatchers.Any(matcher => MatchScores.IsPerfect(matcher.IsMatch(contentType.MimeType))))
|
||||
{
|
||||
return BodyType.MultiPart;
|
||||
}
|
||||
|
||||
return BodyType.Bytes;
|
||||
}
|
||||
|
||||
@@ -82,6 +116,22 @@ namespace WireMock.Util
|
||||
DetectedBodyTypeFromContentType = DetectBodyTypeFromContentType(contentType)
|
||||
};
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
// Try to get the body as String
|
||||
try
|
||||
{
|
||||
|
||||
@@ -28,6 +28,11 @@
|
||||
/// <summary>
|
||||
/// Body is a File
|
||||
/// </summary>
|
||||
File
|
||||
File,
|
||||
|
||||
/// <summary>
|
||||
/// Body is a MultiPart
|
||||
/// </summary>
|
||||
MultiPart
|
||||
}
|
||||
}
|
||||
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.4" />
|
||||
<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 System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Threading.Tasks;
|
||||
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;
|
||||
@@ -19,7 +22,7 @@ namespace WireMock.Net.Tests
|
||||
[Fact]
|
||||
public async Task IFluentMockServerAdmin_GetSettingsAsync()
|
||||
{
|
||||
// Assign
|
||||
// Arrange
|
||||
var server = FluentMockServer.StartWithAdminInterface();
|
||||
var api = RestClient.For<IFluentMockServerAdmin>(server.Urls[0]);
|
||||
|
||||
@@ -31,7 +34,7 @@ namespace WireMock.Net.Tests
|
||||
[Fact]
|
||||
public async Task IFluentMockServerAdmin_PostSettingsAsync()
|
||||
{
|
||||
// Assign
|
||||
// Arrange
|
||||
var server = FluentMockServer.StartWithAdminInterface();
|
||||
var api = RestClient.For<IFluentMockServerAdmin>(server.Urls[0]);
|
||||
|
||||
@@ -44,7 +47,7 @@ namespace WireMock.Net.Tests
|
||||
[Fact]
|
||||
public async Task IFluentMockServerAdmin_PutSettingsAsync()
|
||||
{
|
||||
// Assign
|
||||
// Arrange
|
||||
var server = FluentMockServer.StartWithAdminInterface();
|
||||
var api = RestClient.For<IFluentMockServerAdmin>(server.Urls[0]);
|
||||
|
||||
@@ -57,22 +60,15 @@ namespace WireMock.Net.Tests
|
||||
[Fact]
|
||||
public async Task IFluentMockServerAdmin_PostMappingAsync()
|
||||
{
|
||||
// Assign
|
||||
// Arrange
|
||||
var server = FluentMockServer.StartWithAdminInterface();
|
||||
var api = RestClient.For<IFluentMockServerAdmin>(server.Urls[0]);
|
||||
|
||||
// Act
|
||||
var model = new MappingModel
|
||||
{
|
||||
Request = new RequestModel
|
||||
{
|
||||
Path = "/1"
|
||||
},
|
||||
Response = new ResponseModel
|
||||
{
|
||||
Body = "txt",
|
||||
StatusCode = 200
|
||||
},
|
||||
Request = new RequestModel { Path = "/1" },
|
||||
Response = new ResponseModel { Body = "txt", StatusCode = 200 },
|
||||
Priority = 500,
|
||||
Title = "test"
|
||||
};
|
||||
@@ -90,10 +86,41 @@ namespace WireMock.Net.Tests
|
||||
server.Stop();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task IFluentMockServerAdmin_PostMappingsAsync()
|
||||
{
|
||||
// Arrange
|
||||
var server = FluentMockServer.StartWithAdminInterface();
|
||||
var api = RestClient.For<IFluentMockServerAdmin>(server.Urls[0]);
|
||||
|
||||
// Act
|
||||
var model1 = new MappingModel
|
||||
{
|
||||
Request = new RequestModel { Path = "/1" },
|
||||
Response = new ResponseModel { Body = "txt 1" },
|
||||
Title = "test 1"
|
||||
};
|
||||
var model2 = new MappingModel
|
||||
{
|
||||
Request = new RequestModel { Path = "/2" },
|
||||
Response = new ResponseModel { Body = "txt 2" },
|
||||
Title = "test 2"
|
||||
};
|
||||
var result = await api.PostMappingsAsync(new[] { model1, model2 });
|
||||
|
||||
// Assert
|
||||
Check.That(result).IsNotNull();
|
||||
Check.That(result.Status).IsNotNull();
|
||||
Check.That(result.Guid).IsNull();
|
||||
Check.That(server.Mappings.Where(m => !m.IsAdminInterface)).HasSize(2);
|
||||
|
||||
server.Stop();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task IFluentMockServerAdmin_FindRequestsAsync()
|
||||
{
|
||||
// given
|
||||
// Arrange
|
||||
var server = FluentMockServer.Start(new FluentMockServerSettings
|
||||
{
|
||||
StartAdminInterface = true,
|
||||
@@ -103,10 +130,10 @@ namespace WireMock.Net.Tests
|
||||
await new HttpClient().GetAsync(serverUrl + "/foo");
|
||||
var api = RestClient.For<IFluentMockServerAdmin>(serverUrl);
|
||||
|
||||
// when
|
||||
// Act
|
||||
var requests = await api.FindRequestsAsync(new RequestModel { Methods = new[] { "GET" } });
|
||||
|
||||
// then
|
||||
// Assert
|
||||
Check.That(requests).HasSize(1);
|
||||
var requestLogged = requests.First();
|
||||
Check.That(requestLogged.Request.Method).IsEqualTo("GET");
|
||||
@@ -117,7 +144,7 @@ namespace WireMock.Net.Tests
|
||||
[Fact]
|
||||
public async Task IFluentMockServerAdmin_GetRequestsAsync()
|
||||
{
|
||||
// given
|
||||
// Arrange
|
||||
var server = FluentMockServer.Start(new FluentMockServerSettings
|
||||
{
|
||||
StartAdminInterface = true,
|
||||
@@ -127,10 +154,10 @@ namespace WireMock.Net.Tests
|
||||
await new HttpClient().GetAsync(serverUrl + "/foo");
|
||||
var api = RestClient.For<IFluentMockServerAdmin>(serverUrl);
|
||||
|
||||
// when
|
||||
// Act
|
||||
var requests = await api.GetRequestsAsync();
|
||||
|
||||
// then
|
||||
// Assert
|
||||
Check.That(requests).HasSize(1);
|
||||
var requestLogged = requests.First();
|
||||
Check.That(requestLogged.Request.Method).IsEqualTo("GET");
|
||||
@@ -141,7 +168,7 @@ namespace WireMock.Net.Tests
|
||||
[Fact]
|
||||
public async Task IFluentMockServerAdmin_GetRequestsAsync_JsonApi()
|
||||
{
|
||||
// given
|
||||
// Arrange
|
||||
var server = FluentMockServer.Start(new FluentMockServerSettings
|
||||
{
|
||||
StartAdminInterface = true,
|
||||
@@ -159,13 +186,14 @@ namespace WireMock.Net.Tests
|
||||
request.Content.Headers.ContentType = MediaTypeHeaderValue.Parse(jsonApiContentType);
|
||||
|
||||
var response = await new HttpClient().SendAsync(request);
|
||||
Check.That(response).IsNotNull();
|
||||
|
||||
var api = RestClient.For<IFluentMockServerAdmin>(serverUrl);
|
||||
|
||||
// when
|
||||
// Act
|
||||
var requests = await api.GetRequestsAsync();
|
||||
|
||||
// then
|
||||
// Assert
|
||||
Check.That(requests).HasSize(1);
|
||||
var requestLogged = requests.First();
|
||||
Check.That(requestLogged.Request.Method).IsEqualTo("POST");
|
||||
@@ -176,7 +204,7 @@ namespace WireMock.Net.Tests
|
||||
[Fact]
|
||||
public async Task IFluentMockServerAdmin_GetRequestsAsync_Json()
|
||||
{
|
||||
// given
|
||||
// Arrange
|
||||
var server = FluentMockServer.Start(new FluentMockServerSettings
|
||||
{
|
||||
StartAdminInterface = true,
|
||||
@@ -193,19 +221,251 @@ namespace WireMock.Net.Tests
|
||||
request.Content = new StringContent(data);
|
||||
request.Content.Headers.ContentType = MediaTypeHeaderValue.Parse(jsonApiContentType);
|
||||
var response = await new HttpClient().SendAsync(request);
|
||||
Check.That(response).IsNotNull();
|
||||
|
||||
var api = RestClient.For<IFluentMockServerAdmin>(serverUrl);
|
||||
|
||||
// when
|
||||
// Act
|
||||
var requests = await api.GetRequestsAsync();
|
||||
|
||||
// then
|
||||
// Assert
|
||||
Check.That(requests).HasSize(1);
|
||||
var requestLogged = requests.First();
|
||||
Check.That(requestLogged.Request.Method).IsEqualTo("POST");
|
||||
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;
|
||||
@@ -46,7 +46,7 @@ namespace WireMock.Net.Tests
|
||||
string folder = Path.Combine(GetCurrentFolder(), "__admin", "mappings");
|
||||
server.ReadStaticMappings(folder);
|
||||
|
||||
Check.That(server.Mappings).HasSize(3);
|
||||
Check.That(server.Mappings).HasSize(5);
|
||||
|
||||
// Act
|
||||
server.ResetMappings();
|
||||
@@ -92,8 +92,8 @@ namespace WireMock.Net.Tests
|
||||
|
||||
var server = FluentMockServer.Start();
|
||||
|
||||
string folder = Path.Combine(GetCurrentFolder(), "__admin", "mappings", "documentdb_root.json");
|
||||
server.ReadStaticMappingAndAddOrUpdate(folder);
|
||||
string path = Path.Combine(GetCurrentFolder(), "__admin", "mappings", "documentdb_root.json");
|
||||
server.ReadStaticMappingAndAddOrUpdate(path);
|
||||
|
||||
var mappings = server.Mappings.ToArray();
|
||||
Check.That(mappings).HasSize(1);
|
||||
@@ -110,8 +110,8 @@ namespace WireMock.Net.Tests
|
||||
string guid = "00000002-ee28-4f29-ae63-1ac9b0802d86";
|
||||
|
||||
var server = FluentMockServer.Start();
|
||||
string folder = Path.Combine(GetCurrentFolder(), "__admin", "mappings", guid + ".json");
|
||||
server.ReadStaticMappingAndAddOrUpdate(folder);
|
||||
string path = Path.Combine(GetCurrentFolder(), "__admin", "mappings", guid + ".json");
|
||||
server.ReadStaticMappingAndAddOrUpdate(path);
|
||||
|
||||
var mappings = server.Mappings.ToArray();
|
||||
Check.That(mappings).HasSize(1);
|
||||
@@ -122,13 +122,25 @@ namespace WireMock.Net.Tests
|
||||
Check.That(mappings.First().Title).IsNullOrEmpty();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FluentMockServer_Admin_ReadStaticMapping_WithArray()
|
||||
{
|
||||
var server = FluentMockServer.Start();
|
||||
|
||||
string path = Path.Combine(GetCurrentFolder(), "__admin", "mappings", "array.json");
|
||||
server.ReadStaticMappingAndAddOrUpdate(path);
|
||||
|
||||
var mappings = server.Mappings.ToArray();
|
||||
Check.That(mappings).HasSize(2);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FluentMockServer_Admin_ReadStaticMapping_WithResponseBodyFromFile()
|
||||
{
|
||||
string guid = "00000002-ee28-4f29-ae63-1ac9b0802d87";
|
||||
|
||||
string folder = Path.Combine(GetCurrentFolder(), "__admin", "mappings", guid + ".json");
|
||||
string json = File.ReadAllText(folder);
|
||||
string path = Path.Combine(GetCurrentFolder(), "__admin", "mappings", guid + ".json");
|
||||
string json = File.ReadAllText(path);
|
||||
|
||||
string responseBodyFilePath = Path.Combine(GetCurrentFolder(), "responsebody.json");
|
||||
|
||||
@@ -136,10 +148,10 @@ namespace WireMock.Net.Tests
|
||||
jsonObj["Response"]["BodyAsFile"] = responseBodyFilePath;
|
||||
|
||||
string output = JsonConvert.SerializeObject(jsonObj, Formatting.Indented);
|
||||
File.WriteAllText(folder, output);
|
||||
File.WriteAllText(path, output);
|
||||
|
||||
var server = FluentMockServer.Start();
|
||||
server.ReadStaticMappingAndAddOrUpdate(folder);
|
||||
server.ReadStaticMappingAndAddOrUpdate(path);
|
||||
|
||||
var mappings = server.Mappings.ToArray();
|
||||
Check.That(mappings).HasSize(1);
|
||||
@@ -202,7 +214,7 @@ namespace WireMock.Net.Tests
|
||||
server.ReadStaticMappings(folder);
|
||||
|
||||
var mappings = server.Mappings.ToArray();
|
||||
Check.That(mappings).HasSize(3);
|
||||
Check.That(mappings).HasSize(5);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -363,5 +375,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,63 @@ namespace WireMock.Net.Tests
|
||||
Check.That(response.Headers.Contains("test")).IsTrue();
|
||||
Check.That(response.Headers.Contains("Transfer-Encoding")).IsFalse();
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("GET")]
|
||||
[InlineData("TRACE")]
|
||||
[InlineData("DELETE")]
|
||||
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,17 +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_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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ using Xunit;
|
||||
using Moq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Threading;
|
||||
using WireMock.Handlers;
|
||||
using WireMock.Owin.Mappers;
|
||||
using WireMock.Util;
|
||||
#if NET452
|
||||
@@ -26,6 +27,7 @@ namespace WireMock.Net.Tests.Owin.Mappers
|
||||
private readonly Mock<IResponse> _responseMock;
|
||||
private readonly Mock<Stream> _stream;
|
||||
private readonly Mock<IHeaderDictionary> _headers;
|
||||
private readonly Mock<IFileSystemHandler> _fileSystemHandlerMock;
|
||||
|
||||
public OwinResponseMapperTests()
|
||||
{
|
||||
@@ -46,20 +48,23 @@ namespace WireMock.Net.Tests.Owin.Mappers
|
||||
_responseMock.SetupGet(r => r.Body).Returns(_stream.Object);
|
||||
_responseMock.SetupGet(r => r.Headers).Returns(_headers.Object);
|
||||
|
||||
_sut = new OwinResponseMapper();
|
||||
_fileSystemHandlerMock = new Mock<IFileSystemHandler>();
|
||||
_fileSystemHandlerMock.SetupAllProperties();
|
||||
|
||||
_sut = new OwinResponseMapper(_fileSystemHandlerMock.Object);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async void OwinResponseMapper_MapAsync_Null()
|
||||
public async Task OwinResponseMapper_MapAsync_Null()
|
||||
{
|
||||
// Act
|
||||
await _sut.MapAsync(null, _responseMock.Object);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async void OwinResponseMapper_MapAsync_StatusCode()
|
||||
public async Task OwinResponseMapper_MapAsync_StatusCode()
|
||||
{
|
||||
// Assign
|
||||
// Arrange
|
||||
var responseMessage = new ResponseMessage
|
||||
{
|
||||
StatusCode = 302
|
||||
@@ -73,9 +78,9 @@ namespace WireMock.Net.Tests.Owin.Mappers
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async void OwinResponseMapper_MapAsync_NoBody()
|
||||
public async Task OwinResponseMapper_MapAsync_NoBody()
|
||||
{
|
||||
// Assign
|
||||
// Arrange
|
||||
var responseMessage = new ResponseMessage
|
||||
{
|
||||
Headers = new Dictionary<string, WireMockList<string>>()
|
||||
@@ -89,9 +94,9 @@ namespace WireMock.Net.Tests.Owin.Mappers
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async void OwinResponseMapper_MapAsync_Body()
|
||||
public async Task OwinResponseMapper_MapAsync_Body()
|
||||
{
|
||||
// Assign
|
||||
// Arrange
|
||||
string body = "abc";
|
||||
var responseMessage = new ResponseMessage
|
||||
{
|
||||
@@ -107,9 +112,9 @@ namespace WireMock.Net.Tests.Owin.Mappers
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async void OwinResponseMapper_MapAsync_BodyAsBytes()
|
||||
public async Task OwinResponseMapper_MapAsync_BodyAsBytes()
|
||||
{
|
||||
// Assign
|
||||
// Arrange
|
||||
var bytes = new byte[] { 48, 49 };
|
||||
var responseMessage = new ResponseMessage
|
||||
{
|
||||
@@ -125,9 +130,9 @@ namespace WireMock.Net.Tests.Owin.Mappers
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async void OwinResponseMapper_MapAsync_BodyAsJson()
|
||||
public async Task OwinResponseMapper_MapAsync_BodyAsJson()
|
||||
{
|
||||
// Assign
|
||||
// Arrange
|
||||
var json = new { t = "x", i = (string)null };
|
||||
var responseMessage = new ResponseMessage
|
||||
{
|
||||
@@ -143,9 +148,9 @@ namespace WireMock.Net.Tests.Owin.Mappers
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async void OwinResponseMapper_MapAsync_SetResponseHeaders()
|
||||
public async Task OwinResponseMapper_MapAsync_SetResponseHeaders()
|
||||
{
|
||||
// Assign
|
||||
// Arrange
|
||||
var responseMessage = new ResponseMessage
|
||||
{
|
||||
Headers = new Dictionary<string, WireMockList<string>> { { "h", new WireMockList<string>("x", "y") } }
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,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(((RequestMessageBodyMatcher) matchers[0]).Matcher).IsEqualTo(matcher);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user