mirror of
https://github.com/wiremock/WireMock.Net.git
synced 2026-01-11 22:30:41 +01:00
Compare commits
32 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a5d6061c2d | ||
|
|
395be3c583 | ||
|
|
ea6a8d3b73 | ||
|
|
4886ac6196 | ||
|
|
0ca63eef66 | ||
|
|
c72487a748 | ||
|
|
79db955611 | ||
|
|
395f48a2bf | ||
|
|
596177d4e5 | ||
|
|
fc024678fa | ||
|
|
2e78a04f3d | ||
|
|
f3d2452093 | ||
|
|
92e693818a | ||
|
|
9a1ae6a3f0 | ||
|
|
e701566a1f | ||
|
|
84ad5a927e | ||
|
|
3250604b5a | ||
|
|
9d2963632e | ||
|
|
9e0536c54c | ||
|
|
676e973011 | ||
|
|
31f3d77b38 | ||
|
|
4a2d512f83 | ||
|
|
87534c35f5 | ||
|
|
7789f94737 | ||
|
|
b2167f85ae | ||
|
|
3cc361e216 | ||
|
|
0a9214ef47 | ||
|
|
4afef3695b | ||
|
|
782b082949 | ||
|
|
36325fe2c7 | ||
|
|
01171b9592 | ||
|
|
d6f44b2202 |
53
CHANGELOG.md
53
CHANGELOG.md
@@ -1,9 +1,42 @@
|
||||
# 1.0.37.0 (08 November 2019)
|
||||
- [#373](https://github.com/WireMock-Net/WireMock.Net/pull/373) - Make Sonar and WhiteSource optional in the Azure pipelines build [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#374](https://github.com/WireMock-Net/WireMock.Net/pull/374) - WatchStaticMappingsInSubdirectories [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#372](https://github.com/WireMock-Net/WireMock.Net/issues/372) - Reset in WireMock admin API not working fine. [feature, question]
|
||||
|
||||
# 1.0.36.0 (26 October 2019)
|
||||
- [#360](https://github.com/WireMock-Net/WireMock.Net/pull/360) - Add support for Faults [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#343](https://github.com/WireMock-Net/WireMock.Net/issues/343) - Feature: Please provide support for Bad responses. [feature]
|
||||
|
||||
# 1.0.35.0 (25 October 2019)
|
||||
- [#367](https://github.com/WireMock-Net/WireMock.Net/pull/367) - No symbol NuGets [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#368](https://github.com/WireMock-Net/WireMock.Net/pull/368) - Remove Obsolete annotations [feature] contributed by [StefH](https://github.com/StefH)
|
||||
|
||||
# 1.0.34.0 (22 October 2019)
|
||||
- [#354](https://github.com/WireMock-Net/WireMock.Net/pull/354) - AllowBodyForAllHttpMethods [bug, feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#365](https://github.com/WireMock-Net/WireMock.Net/pull/365) - Bump Microsoft.AspNetCore.All from 2.0.8 to 2.0.9 in /examples/WireMock.Net.WebApplication [dependencies] contributed by [dependabot[bot]](https://github.com/apps/dependabot)
|
||||
- [#366](https://github.com/WireMock-Net/WireMock.Net/pull/366) - Update ObsoleteAnnotations [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#352](https://github.com/WireMock-Net/WireMock.Net/issues/352) - DELETE request drops the body [feature, question]
|
||||
|
||||
# 1.0.33.0 (12 October 2019)
|
||||
- [#311](https://github.com/WireMock-Net/WireMock.Net/pull/311) - fix jsonpath matcher [bug] contributed by [StefH](https://github.com/StefH)
|
||||
- [#324](https://github.com/WireMock-Net/WireMock.Net/pull/324) - Add CSharpCodeMatcher [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#353](https://github.com/WireMock-Net/WireMock.Net/pull/353) - Fixed failing admin requests when content type includes a charset (based on idea from Paul Roub) [bug] contributed by [StefH](https://github.com/StefH)
|
||||
- [#355](https://github.com/WireMock-Net/WireMock.Net/pull/355) - Add Try-Catch to the event LogEntriesChanged [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#357](https://github.com/WireMock-Net/WireMock.Net/pull/357) - Add Proxy Setting for: SaveMappingForStatusCodePattern to only save the mapping when the status code matches the pattern [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#358](https://github.com/WireMock-Net/WireMock.Net/pull/358) - Fix JsonMatcher (parsing DateTimeOffset) contributed by [StefH](https://github.com/StefH)
|
||||
- [#306](https://github.com/WireMock-Net/WireMock.Net/issues/306) - Writing to the response body is invalid for responses with status code 204 [bug]
|
||||
- [#307](https://github.com/WireMock-Net/WireMock.Net/issues/307) - JsonPathMatcher always convert to JArray before matching [bug]
|
||||
- [#329](https://github.com/WireMock-Net/WireMock.Net/issues/329) - Feature: Add support for CSharpCodeMatcher [feature]
|
||||
- [#350](https://github.com/WireMock-Net/WireMock.Net/issues/350) - Admin requests fail when content type includes a charset [bug]
|
||||
- [#356](https://github.com/WireMock-Net/WireMock.Net/issues/356) - JsonMatcher not working when JSON contains a DateTimeOffset
|
||||
|
||||
# 1.0.32.0 (20 September 2019)
|
||||
- [#348](https://github.com/WireMock-Net/WireMock.Net/pull/348) - When posting new mapping, use DateParseHandling.None [bug] contributed by [StefH](https://github.com/StefH)
|
||||
- [#347](https://github.com/WireMock-Net/WireMock.Net/issues/347) - Query string match on DateTimeOffset is not working [bug]
|
||||
|
||||
# 1.0.31.0 (19 September 2019)
|
||||
- [#334](https://github.com/WireMock-Net/WireMock.Net/pull/334) - Fix issues with Proxy mode and Binary Request Bodies [bug] contributed by [andi0b](https://github.com/andi0b)
|
||||
- [#338](https://github.com/WireMock-Net/WireMock.Net/pull/338) - Fix ContentType with parameters in Proxy Mode [bug] contributed by [StefH](https://github.com/StefH)
|
||||
- [#339](https://github.com/WireMock-Net/WireMock.Net/pull/339) - Fix ConcurrentObservableCollection [bug] contributed by [StefH](https://github.com/StefH)
|
||||
- [#345](https://github.com/WireMock-Net/WireMock.Net/pull/345) - Fix CompareTo in RequestMatchResult [bug] contributed by [StefH](https://github.com/StefH)
|
||||
- [#346](https://github.com/WireMock-Net/WireMock.Net/pull/346) - Fix recorded requests skipped by request logger contributed by [vitaliydavydiak](https://github.com/vitaliydavydiak)
|
||||
@@ -11,9 +44,6 @@
|
||||
- [#337](https://github.com/WireMock-Net/WireMock.Net/issues/337) - Proxy Missing header Content-Type - tried with Recording [bug]
|
||||
- [#344](https://github.com/WireMock-Net/WireMock.Net/issues/344) - Mapping adding order matters for multiple mappings? [bug]
|
||||
|
||||
# 1.0.30.0 (31 August 2019)
|
||||
- [#338](https://github.com/WireMock-Net/WireMock.Net/pull/338) - Fix ContentType with parameters in Proxy Mode [bug] contributed by [StefH](https://github.com/StefH)
|
||||
|
||||
# 1.0.29.0 (29 August 2019)
|
||||
- [#328](https://github.com/WireMock-Net/WireMock.Net/pull/328) - Fix LogRequest : Index Out Of Bounds [bug] contributed by [StefH](https://github.com/StefH)
|
||||
- [#331](https://github.com/WireMock-Net/WireMock.Net/pull/331) - Fix: Collection was modified exception [bug] contributed by [theramis](https://github.com/theramis)
|
||||
@@ -21,26 +51,19 @@
|
||||
- [#332](https://github.com/WireMock-Net/WireMock.Net/issues/332) - Case sensitive true is ignored for JsonMatcher [feature]
|
||||
|
||||
# 1.0.28.0 (20 August 2019)
|
||||
- [#309](https://github.com/WireMock-Net/WireMock.Net/pull/309) - Fix LogEntries: collection was modified exception [bug] contributed by [StefH](https://github.com/StefH)
|
||||
- [#314](https://github.com/WireMock-Net/WireMock.Net/pull/314) - RequestLogExpirationDuration : use DateTime.UtcNow [bug] contributed by [StefH](https://github.com/StefH)
|
||||
- [#316](https://github.com/WireMock-Net/WireMock.Net/pull/316) - Handles case where parameter value contains == [feature] contributed by [lobsteropteryx](https://github.com/lobsteropteryx)
|
||||
- [#317](https://github.com/WireMock-Net/WireMock.Net/pull/317) - Make SaveMapping and SaveMappingToFile settings independent. [feature] contributed by [vitaliydavydiak](https://github.com/vitaliydavydiak)
|
||||
- [#319](https://github.com/WireMock-Net/WireMock.Net/pull/319) - Add blacklist for Request Cookies. contributed by [vitaliydavydiak](https://github.com/vitaliydavydiak)
|
||||
- [#320](https://github.com/WireMock-Net/WireMock.Net/pull/320) - Remove coverlet folder from source control [doc] contributed by [StefH](https://github.com/StefH)
|
||||
- [#322](https://github.com/WireMock-Net/WireMock.Net/pull/322) - Fix MappingMatcher in case of an exception in LinqMatcher. [bug] contributed by [StefH](https://github.com/StefH)
|
||||
- [#323](https://github.com/WireMock-Net/WireMock.Net/pull/323) - Refactor MappingConverter & MatcherMapper [refactor] contributed by [StefH](https://github.com/StefH)
|
||||
- [#326](https://github.com/WireMock-Net/WireMock.Net/pull/326) - Fix Parsing Guid in PUT Mapping [bug] contributed by [StefH](https://github.com/StefH)
|
||||
- [#318](https://github.com/WireMock-Net/WireMock.Net/issues/318) - Documentation: Add valid CLI parameters [doc, question]
|
||||
- [#325](https://github.com/WireMock-Net/WireMock.Net/issues/325) - Admin API: PUT Mapping, FormatException because of wrong parsing of the Query [bug]
|
||||
|
||||
# 1.0.27.0 (14 August 2019)
|
||||
- [#316](https://github.com/WireMock-Net/WireMock.Net/pull/316) - Handles case where parameter value contains == [feature] contributed by [lobsteropteryx](https://github.com/lobsteropteryx)
|
||||
- [#287](https://github.com/WireMock-Net/WireMock.Net/issues/287) - Error with parameter that contains a "=" character [bug, question]
|
||||
- [#315](https://github.com/WireMock-Net/WireMock.Net/issues/315) - Wiki - Proxying: AtPriority() example not set on right object [doc]
|
||||
|
||||
# 1.0.26.0 (11 August 2019)
|
||||
- [#309](https://github.com/WireMock-Net/WireMock.Net/pull/309) - Fix LogEntries: collection was modified exception [bug] contributed by [StefH](https://github.com/StefH)
|
||||
- [#314](https://github.com/WireMock-Net/WireMock.Net/pull/314) - RequestLogExpirationDuration : use DateTime.UtcNow [bug] contributed by [StefH](https://github.com/StefH)
|
||||
- [#252](https://github.com/WireMock-Net/WireMock.Net/issues/252) - Proxy with Transform
|
||||
- [#287](https://github.com/WireMock-Net/WireMock.Net/issues/287) - Error with parameter that contains a "=" character [bug, question]
|
||||
- [#308](https://github.com/WireMock-Net/WireMock.Net/issues/308) - __admin/requests - "Collection was modified" exception [bug]
|
||||
- [#313](https://github.com/WireMock-Net/WireMock.Net/issues/313) - RequestLogExpirationDuration - bug [bug]
|
||||
- [#325](https://github.com/WireMock-Net/WireMock.Net/issues/325) - Admin API: PUT Mapping, FormatException because of wrong parsing of the Query [bug]
|
||||
|
||||
# 1.0.25.0 (23 July 2019)
|
||||
- [#304](https://github.com/WireMock-Net/WireMock.Net/pull/304) - Support WithBody with multiple matchers [feature] contributed by [StefH](https://github.com/StefH)
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<VersionPrefix>1.0.32</VersionPrefix>
|
||||
<VersionPrefix>1.0.37</VersionPrefix>
|
||||
</PropertyGroup>
|
||||
|
||||
<Choose>
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
https://github.com/StefH/GitHubReleaseNotes
|
||||
|
||||
GitHubReleaseNotes.exe --output CHANGELOG.md --skip-empty-releases --exclude-labels question invalid --version 1.0.32.0
|
||||
GitHubReleaseNotes.exe --output CHANGELOG.md --skip-empty-releases --exclude-labels question invalid doc --version 1.0.37.0
|
||||
@@ -9,6 +9,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
.runsettings = .runsettings
|
||||
azure-pipelines-linux.yml = azure-pipelines-linux.yml
|
||||
azure-pipelines-nuget.yml = azure-pipelines-nuget.yml
|
||||
azure-pipelines.yml = azure-pipelines.yml
|
||||
build-info.md = build-info.md
|
||||
CHANGELOG.md = CHANGELOG.md
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=CS/@EntryIndexedValue">CS</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=ID/@EntryIndexedValue">ID</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=IP/@EntryIndexedValue">IP</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=MD/@EntryIndexedValue">MD5</s:String>
|
||||
|
||||
46
azure-pipelines-nuget.yml
Normal file
46
azure-pipelines-nuget.yml
Normal file
@@ -0,0 +1,46 @@
|
||||
pool:
|
||||
vmImage: 'vs2017-win2016'
|
||||
|
||||
variables:
|
||||
Prerelease: ''
|
||||
buildId: "1$(Build.BuildId)"
|
||||
buildProjects: '**/src/**/*.csproj'
|
||||
|
||||
steps:
|
||||
# Print buildId
|
||||
- script: |
|
||||
echo "BuildId = $(buildId)"
|
||||
displayName: 'Print buildId'
|
||||
|
||||
# Based on https://whereslou.com/2018/09/versioning-and-publishing-nuget-packages-automatically-using-azure-devops-pipelines/
|
||||
- task: DotNetCoreCLI@2
|
||||
displayName: Build Release
|
||||
inputs:
|
||||
command: 'build'
|
||||
arguments: /p:Configuration=Release # https://github.com/MicrosoftDocs/vsts-docs/issues/1976
|
||||
projects: $(buildProjects)
|
||||
|
||||
- task: DotNetCoreCLI@2
|
||||
displayName: Pack
|
||||
condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest')) # Do not run for PullRequests
|
||||
inputs:
|
||||
command: pack
|
||||
configuration: 'Release'
|
||||
packagesToPack: $(buildProjects)
|
||||
nobuild: true
|
||||
packDirectory: '$(Build.ArtifactStagingDirectory)/packages'
|
||||
verbosityPack: 'normal'
|
||||
|
||||
- task: PublishBuildArtifacts@1
|
||||
displayName: Publish Artifacts
|
||||
condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest')) # Do not run for PullRequests
|
||||
inputs:
|
||||
PathtoPublish: '$(Build.ArtifactStagingDirectory)'
|
||||
|
||||
- task: DotNetCoreCLI@2
|
||||
displayName: Push to NuGet
|
||||
condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest')) # Do not run for PullRequests
|
||||
inputs:
|
||||
command: custom
|
||||
custom: nuget
|
||||
arguments: push $(Build.ArtifactStagingDirectory)\packages\*.nupkg --source https://api.nuget.org/v3/index.json --no-service-endpoint --api-key $(NuGetKey)
|
||||
@@ -1,5 +1,5 @@
|
||||
pool:
|
||||
vmImage: 'vs2017-win2016'
|
||||
vmImage: 'windows-2019'
|
||||
|
||||
variables:
|
||||
Prerelease: 'ci'
|
||||
@@ -26,6 +26,7 @@ steps:
|
||||
- script: |
|
||||
%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
|
||||
condition: and(succeeded(), eq(variables['RUN_SONAR'], 'yes'))
|
||||
|
||||
# Build source, tests and run tests for net452 and netcoreapp2.1 (with coverage)
|
||||
- script: |
|
||||
@@ -37,9 +38,11 @@ steps:
|
||||
- script: |
|
||||
%USERPROFILE%\.dotnet\tools\dotnet-sonarscanner end /d:sonar.login="$(SONAR_TOKEN)"
|
||||
displayName: End SonarScanner
|
||||
condition: and(succeeded(), eq(variables['RUN_SONAR'], 'yes'))
|
||||
|
||||
- task: whitesource.ws-bolt.bolt.wss.WhiteSource Bolt@19
|
||||
displayName: 'WhiteSource Bolt'
|
||||
condition: and(succeeded(), eq(variables['RUN_WHITESOURCE'], 'yes'))
|
||||
|
||||
# Upload coverage to codecov.io
|
||||
- script: |
|
||||
@@ -82,4 +85,4 @@ steps:
|
||||
inputs:
|
||||
command: custom
|
||||
custom: nuget
|
||||
arguments: push $(Build.ArtifactStagingDirectory)\packages\*.nupkg --source https://www.myget.org/F/wiremock-net/api/v3/index.json --no-service-endpoint --api-key $(MyGetKey)
|
||||
arguments: push $(Build.ArtifactStagingDirectory)\packages\*.nupkg -n true -s https://www.myget.org/F/wiremock-net/api/v3/index.json -k $(MyGetKey)
|
||||
@@ -3,13 +3,14 @@ using RestEase;
|
||||
using System;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using WireMock.Client;
|
||||
|
||||
namespace WireMock.Net.Client
|
||||
{
|
||||
class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
static async Task Main(string[] args)
|
||||
{
|
||||
// Create an implementation of the IFluentMockServerAdmin and pass in the base URL for the API.
|
||||
var api = RestClient.For<IFluentMockServerAdmin>("http://localhost:9091");
|
||||
@@ -18,29 +19,29 @@ namespace WireMock.Net.Client
|
||||
var value = Convert.ToBase64String(Encoding.ASCII.GetBytes("a:b"));
|
||||
api.Authorization = new AuthenticationHeaderValue("Basic", value);
|
||||
|
||||
var settings1 = api.GetSettingsAsync().Result;
|
||||
var settings1 = await api.GetSettingsAsync();
|
||||
Console.WriteLine($"settings1 = {JsonConvert.SerializeObject(settings1)}");
|
||||
|
||||
settings1.GlobalProcessingDelay = 1077;
|
||||
api.PostSettingsAsync(settings1).Wait();
|
||||
|
||||
var settings2 = api.GetSettingsAsync().Result;
|
||||
var settings2 = await api.GetSettingsAsync();
|
||||
Console.WriteLine($"settings2 = {JsonConvert.SerializeObject(settings2)}");
|
||||
|
||||
var mappings = api.GetMappingsAsync().Result;
|
||||
var mappings = await api.GetMappingsAsync();
|
||||
Console.WriteLine($"mappings = {JsonConvert.SerializeObject(mappings)}");
|
||||
|
||||
try
|
||||
{
|
||||
var guid = Guid.Parse("11111110-a633-40e8-a244-5cb80bc0ab66");
|
||||
var mapping = api.GetMappingAsync(guid).Result;
|
||||
var mapping = await api.GetMappingAsync(guid);
|
||||
Console.WriteLine($"mapping = {JsonConvert.SerializeObject(mapping)}");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
}
|
||||
|
||||
var request = api.GetRequestsAsync().Result;
|
||||
var request = await api.GetRequestsAsync();
|
||||
Console.WriteLine($"request = {JsonConvert.SerializeObject(request)}");
|
||||
|
||||
//var deleteRequestsAsync = api.DeleteRequestsAsync().Result;
|
||||
@@ -49,15 +50,21 @@ namespace WireMock.Net.Client
|
||||
//var resetRequestsAsync = api.ResetRequestsAsync().Result;
|
||||
//Console.WriteLine($"ResetRequestsAsync = {resetRequestsAsync.Status}");
|
||||
|
||||
var scenarioStates = api.GetScenariosAsync().Result;
|
||||
var scenarioStates = await api.GetScenariosAsync();
|
||||
Console.WriteLine($"GetScenariosAsync = {JsonConvert.SerializeObject(scenarioStates)}");
|
||||
|
||||
var postFileResult = api.PostFileAsync("1.cs", "C# Hello").GetAwaiter().GetResult();
|
||||
var postFileResult = await api.PostFileAsync("1.cs", "C# Hello");
|
||||
Console.WriteLine($"postFileResult = {JsonConvert.SerializeObject(postFileResult)}");
|
||||
|
||||
var getFileResult = api.GetFileAsync("1.cs").GetAwaiter().GetResult();
|
||||
var getFileResult = await api.GetFileAsync("1.cs");
|
||||
Console.WriteLine($"getFileResult = {getFileResult}");
|
||||
|
||||
var resetMappingsAsync = await api.ResetMappingsAsync();
|
||||
Console.WriteLine($"resetMappingsAsync = {resetMappingsAsync.Status}");
|
||||
|
||||
var resetMappingsAndReloadStaticMappingsAsync = await api.ResetMappingsAsync(true);
|
||||
Console.WriteLine($"resetMappingsAndReloadStaticMappingsAsync = {resetMappingsAndReloadStaticMappingsAsync.Status}");
|
||||
|
||||
Console.WriteLine("Press any key to quit");
|
||||
Console.ReadKey();
|
||||
}
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp2.0</TargetFramework>
|
||||
<!-- <RuntimeFrameworkVersion>1.0.1</RuntimeFrameworkVersion> -->
|
||||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
||||
<ApplicationIcon>../../WireMock.Net-Logo.ico</ApplicationIcon>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
C# Hello
|
||||
@@ -21,9 +21,9 @@ namespace WireMock.Net.ConsoleApplication
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IFileSystemHandler.EnumerateFiles"/>
|
||||
public IEnumerable<string> EnumerateFiles(string path)
|
||||
public IEnumerable<string> EnumerateFiles(string path, bool includeSubdirectories)
|
||||
{
|
||||
return Directory.EnumerateFiles(path);
|
||||
return includeSubdirectories ? Directory.EnumerateFiles(path, "*", SearchOption.AllDirectories) : Directory.EnumerateFiles(path);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IFileSystemHandler.GetMappingFolder"/>
|
||||
|
||||
@@ -41,10 +41,12 @@ namespace WireMock.Net.ConsoleApplication
|
||||
|
||||
var server = FluentMockServer.Start(new FluentMockServerSettings
|
||||
{
|
||||
AllowCSharpCodeMatcher = true,
|
||||
Urls = new[] { url1, url2, url3 },
|
||||
StartAdminInterface = true,
|
||||
ReadStaticMappings = true,
|
||||
WatchStaticMappings = true,
|
||||
WatchStaticMappingsInSubdirectories = true,
|
||||
//ProxyAndRecordSettings = new ProxyAndRecordSettings
|
||||
//{
|
||||
// SaveMapping = true
|
||||
|
||||
@@ -11,13 +11,13 @@
|
||||
|
||||
<ItemGroup Condition=" '$(TargetFramework)' == 'netcoreapp2.0'">
|
||||
<DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.2" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.8" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.9" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition=" '$(TargetFramework)' == 'netcoreapp2.1'">
|
||||
<DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.4" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.1.5" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.All" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
BIN
resources/MyGet-Config.png
Normal file
BIN
resources/MyGet-Config.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 31 KiB |
BIN
resources/MyGet-Use.png
Normal file
BIN
resources/MyGet-Use.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 62 KiB |
@@ -1,9 +1,10 @@
|
||||
using System.Linq;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using JetBrains.Annotations;
|
||||
using WireMock.Logging;
|
||||
using WireMock.Server;
|
||||
using WireMock.Settings;
|
||||
using WireMock.Validation;
|
||||
using JetBrains.Annotations;
|
||||
using WireMock.Logging;
|
||||
|
||||
namespace WireMock.Net.StandAlone
|
||||
{
|
||||
@@ -46,11 +47,14 @@ namespace WireMock.Net.StandAlone
|
||||
StartAdminInterface = parser.GetBoolValue("StartAdminInterface", true),
|
||||
ReadStaticMappings = parser.GetBoolValue("ReadStaticMappings"),
|
||||
WatchStaticMappings = parser.GetBoolValue("WatchStaticMappings"),
|
||||
AllowPartialMapping = parser.GetBoolValue("AllowPartialMapping", false),
|
||||
WatchStaticMappingsInSubdirectories = parser.GetBoolValue("WatchStaticMappingsInSubdirectories"),
|
||||
AllowPartialMapping = parser.GetBoolValue("AllowPartialMapping"),
|
||||
AdminUsername = parser.GetStringValue("AdminUsername"),
|
||||
AdminPassword = parser.GetStringValue("AdminPassword"),
|
||||
MaxRequestLogCount = parser.GetIntValue("MaxRequestLogCount"),
|
||||
RequestLogExpirationDuration = parser.GetIntValue("RequestLogExpirationDuration")
|
||||
RequestLogExpirationDuration = parser.GetIntValue("RequestLogExpirationDuration"),
|
||||
AllowCSharpCodeMatcher = parser.GetBoolValue("AllowCSharpCodeMatcher"),
|
||||
AllowBodyForAllHttpMethods = parser.GetBoolValue("AllowBodyForAllHttpMethods")
|
||||
};
|
||||
|
||||
if (logger != null)
|
||||
@@ -80,9 +84,10 @@ namespace WireMock.Net.StandAlone
|
||||
Url = proxyURL,
|
||||
SaveMapping = parser.GetBoolValue("SaveMapping"),
|
||||
SaveMappingToFile = parser.GetBoolValue("SaveMappingToFile"),
|
||||
SaveMappingForStatusCodePattern = parser.GetStringValue("SaveMappingForStatusCodePattern"),
|
||||
ClientX509Certificate2ThumbprintOrSubjectName = parser.GetStringValue("ClientX509Certificate2ThumbprintOrSubjectName"),
|
||||
BlackListedHeaders = parser.GetValues("BlackListedHeaders"),
|
||||
BlackListedCookies = parser.GetValues("BlackListedCookies")
|
||||
BlackListedCookies = parser.GetValues("BlackListedCookies")
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -11,14 +11,14 @@
|
||||
<PackageReleaseNotes>See CHANGELOG.md</PackageReleaseNotes>
|
||||
<PackageIconUrl>https://raw.githubusercontent.com/WireMock-Net/WireMock.Net/master/WireMock.Net-Logo.png</PackageIconUrl>
|
||||
<PackageProjectUrl>https://github.com/WireMock-Net/WireMock.Net</PackageProjectUrl>
|
||||
<PackageLicenseUrl>https://raw.githubusercontent.com/WireMock-Net/WireMock.Net/master/LICENSE</PackageLicenseUrl>
|
||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||
<RepositoryType>git</RepositoryType>
|
||||
<RepositoryUrl>https://github.com/WireMock-Net/WireMock.Net</RepositoryUrl>
|
||||
<ApplicationIcon>../../WireMock.Net-Logo.ico</ApplicationIcon>
|
||||
<RootNamespace>WireMock.Net.StandAlone</RootNamespace>
|
||||
<DebugType>full</DebugType>
|
||||
<!--<DebugType>full</DebugType>
|
||||
<IncludeSource>True</IncludeSource>
|
||||
<IncludeSymbols>True</IncludeSymbols>
|
||||
<IncludeSymbols>True</IncludeSymbols>-->
|
||||
<ProjectGuid>{B6269AAC-170A-43D5-8B9A-579DED3D9A95}</ProjectGuid>
|
||||
<PublishRepositoryUrl>true</PublishRepositoryUrl>
|
||||
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
|
||||
|
||||
18
src/WireMock.Net/Admin/Mappings/FaultModel.cs
Normal file
18
src/WireMock.Net/Admin/Mappings/FaultModel.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
namespace WireMock.Admin.Mappings
|
||||
{
|
||||
/// <summary>
|
||||
/// Fault Model
|
||||
/// </summary>
|
||||
public class FaultModel
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the fault. Can be null, "", NONE, EMPTY_RESPONSE, MALFORMED_RESPONSE_CHUNK or RANDOM_DATA_THEN_CLOSE.
|
||||
/// </summary>
|
||||
public string Type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the fault percentage.
|
||||
/// </summary>
|
||||
public double? Percentage { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -86,5 +86,10 @@ namespace WireMock.Admin.Mappings
|
||||
/// The client X509Certificate2 Thumbprint or SubjectName to use.
|
||||
/// </summary>
|
||||
public string X509Certificate2ThumbprintOrSubjectName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the fault.
|
||||
/// </summary>
|
||||
public FaultModel Fault { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Collections.Generic;
|
||||
using WireMock.Admin.Mappings;
|
||||
using WireMock.ResponseBuilders;
|
||||
using WireMock.Util;
|
||||
|
||||
namespace WireMock.Admin.Requests
|
||||
@@ -68,5 +69,15 @@ namespace WireMock.Admin.Requests
|
||||
/// The detected body type (detection based on Content-Type).
|
||||
/// </summary>
|
||||
public BodyType DetectedBodyTypeFromContentType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The FaultType.
|
||||
/// </summary>
|
||||
public string FaultType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Fault percentage.
|
||||
/// </summary>
|
||||
public double? FaultPercentage { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -24,5 +24,10 @@
|
||||
/// Gets or sets the MaxRequestLog count.
|
||||
/// </summary>
|
||||
public int? MaxRequestLogCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets wether to allow a body for all HTTP methods.
|
||||
/// </summary>
|
||||
public bool? AllowBodyForAllHttpMethods { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -75,8 +75,9 @@ namespace WireMock.Client
|
||||
/// <summary>
|
||||
/// Delete (reset) all mappings.
|
||||
/// </summary>
|
||||
/// <param name="reloadStaticMappings">A value indicating whether to reload the static mappings after the reset.</param>
|
||||
[Post("__admin/mappings/reset")]
|
||||
Task<StatusModel> ResetMappingsAsync();
|
||||
Task<StatusModel> ResetMappingsAsync(bool? reloadStaticMappings = false);
|
||||
|
||||
/// <summary>
|
||||
/// Get a mapping based on the guid
|
||||
|
||||
@@ -31,8 +31,9 @@ namespace WireMock.Handlers
|
||||
/// 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([NotNull] string path);
|
||||
/// <param name="includeSubdirectories">A value indicating whether subdirectories should also included when enumerating files.</param>
|
||||
/// <returns>An enumerable collection of the full names (including paths) for the files in the directory (and optionally subdirectories) specified by path.</returns>
|
||||
IEnumerable<string> EnumerateFiles([NotNull] string path, bool includeSubdirectories);
|
||||
|
||||
/// <summary>
|
||||
/// Read a static mapping file as text.
|
||||
|
||||
@@ -46,11 +46,11 @@ namespace WireMock.Handlers
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IFileSystemHandler.EnumerateFiles"/>
|
||||
public IEnumerable<string> EnumerateFiles(string path)
|
||||
public IEnumerable<string> EnumerateFiles(string path, bool includeSubdirectories)
|
||||
{
|
||||
Check.NotNullOrEmpty(path, nameof(path));
|
||||
|
||||
return Directory.EnumerateFiles(path);
|
||||
return includeSubdirectories ? Directory.EnumerateFiles(path, "*", SearchOption.AllDirectories) : Directory.EnumerateFiles(path);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IFileSystemHandler.GetMappingFolder"/>
|
||||
|
||||
197
src/WireMock.Net/Matchers/CSharpCodeMatcher.cs
Normal file
197
src/WireMock.Net/Matchers/CSharpCodeMatcher.cs
Normal file
@@ -0,0 +1,197 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using JetBrains.Annotations;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using WireMock.Exceptions;
|
||||
using WireMock.Validation;
|
||||
|
||||
namespace WireMock.Matchers
|
||||
{
|
||||
/// <summary>
|
||||
/// CSharpCode / CS-Script Matcher
|
||||
/// </summary>
|
||||
/// <inheritdoc cref="IObjectMatcher"/>
|
||||
/// <inheritdoc cref="IStringMatcher"/>
|
||||
internal class CSharpCodeMatcher : IObjectMatcher, IStringMatcher
|
||||
{
|
||||
private const string TemplateForIsMatchWithString = "{0} public class CodeHelper {{ public bool IsMatch(string it) {{ {1} }} }}";
|
||||
|
||||
private const string TemplateForIsMatchWithDynamic = "{0} public class CodeHelper {{ public bool IsMatch(dynamic it) {{ {1} }} }}";
|
||||
|
||||
private readonly string[] _usings =
|
||||
{
|
||||
"System",
|
||||
"System.Linq",
|
||||
"System.Collections.Generic",
|
||||
"Microsoft.CSharp",
|
||||
"Newtonsoft.Json.Linq"
|
||||
};
|
||||
|
||||
public MatchBehaviour MatchBehaviour { get; }
|
||||
|
||||
private readonly string[] _patterns;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CSharpCodeMatcher"/> class.
|
||||
/// </summary>
|
||||
/// <param name="patterns">The patterns.</param>
|
||||
public CSharpCodeMatcher([NotNull] params string[] patterns) : this(MatchBehaviour.AcceptOnMatch, patterns)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CSharpCodeMatcher"/> class.
|
||||
/// </summary>
|
||||
/// <param name="matchBehaviour">The match behaviour.</param>
|
||||
/// <param name="patterns">The patterns.</param>
|
||||
public CSharpCodeMatcher(MatchBehaviour matchBehaviour, [NotNull] params string[] patterns)
|
||||
{
|
||||
Check.NotNull(patterns, nameof(patterns));
|
||||
|
||||
MatchBehaviour = matchBehaviour;
|
||||
_patterns = patterns;
|
||||
}
|
||||
|
||||
public double IsMatch(string input)
|
||||
{
|
||||
return IsMatchInternal(input);
|
||||
}
|
||||
|
||||
public double IsMatch(object input)
|
||||
{
|
||||
return IsMatchInternal(input);
|
||||
}
|
||||
|
||||
public double IsMatchInternal(object input)
|
||||
{
|
||||
double match = MatchScores.Mismatch;
|
||||
|
||||
if (input != null)
|
||||
{
|
||||
match = MatchScores.ToScore(_patterns.Select(pattern => IsMatch(input, pattern)));
|
||||
}
|
||||
|
||||
return MatchBehaviourHelper.Convert(MatchBehaviour, match);
|
||||
}
|
||||
|
||||
private bool IsMatch(dynamic input, string pattern)
|
||||
{
|
||||
bool isMatchWithString = input is string;
|
||||
var inputValue = isMatchWithString ? input : JObject.FromObject(input);
|
||||
string source = GetSourceForIsMatchWithString(pattern, isMatchWithString);
|
||||
|
||||
object result = null;
|
||||
|
||||
#if NET451 || NET452
|
||||
var compilerParams = new System.CodeDom.Compiler.CompilerParameters
|
||||
{
|
||||
GenerateInMemory = true,
|
||||
GenerateExecutable = false,
|
||||
ReferencedAssemblies =
|
||||
{
|
||||
"System.dll",
|
||||
"System.Core.dll",
|
||||
"Microsoft.CSharp.dll",
|
||||
"Newtonsoft.Json.dll"
|
||||
}
|
||||
};
|
||||
|
||||
using (var codeProvider = new Microsoft.CSharp.CSharpCodeProvider())
|
||||
{
|
||||
var compilerResults = codeProvider.CompileAssemblyFromSource(compilerParams, source);
|
||||
|
||||
if (compilerResults.Errors.Count != 0)
|
||||
{
|
||||
var errors = from System.CodeDom.Compiler.CompilerError er in compilerResults.Errors select er.ToString();
|
||||
throw new WireMockException(string.Join(", ", errors));
|
||||
}
|
||||
|
||||
object helper = compilerResults.CompiledAssembly.CreateInstance("CodeHelper");
|
||||
if (helper == null)
|
||||
{
|
||||
throw new WireMockException("CSharpCodeMatcher: Unable to create instance from WireMock.CodeHelper");
|
||||
}
|
||||
|
||||
var methodInfo = helper.GetType().GetMethod("IsMatch");
|
||||
if (methodInfo == null)
|
||||
{
|
||||
throw new WireMockException("CSharpCodeMatcher: Unable to find method 'IsMatch' in WireMock.CodeHelper");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
result = methodInfo.Invoke(helper, new[] { inputValue });
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw new WireMockException("CSharpCodeMatcher: Unable to call method 'IsMatch' in WireMock.CodeHelper");
|
||||
}
|
||||
}
|
||||
#elif NET46 || NET461
|
||||
dynamic script;
|
||||
try
|
||||
{
|
||||
script = CSScriptLibrary.CSScript.Evaluator.CompileCode(source).CreateObject("*");
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw new WireMockException("CSharpCodeMatcher: Unable to create compiler for WireMock.CodeHelper");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
result = script.IsMatch(inputValue);
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw new WireMockException("CSharpCodeMatcher: Problem calling method 'IsMatch' in WireMock.CodeHelper");
|
||||
}
|
||||
#elif NETSTANDARD2_0
|
||||
dynamic script;
|
||||
try
|
||||
{
|
||||
var assembly = CSScriptLib.CSScript.Evaluator.CompileCode(source);
|
||||
script = csscript.GenericExtensions.CreateObject(assembly, "*");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new WireMockException("CSharpCodeMatcher: Unable to compile code for WireMock.CodeHelper", ex);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
result = script.IsMatch(inputValue);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new WireMockException("CSharpCodeMatcher: Problem calling method 'IsMatch' in WireMock.CodeHelper");
|
||||
}
|
||||
#else
|
||||
throw new NotSupportedException("The 'CSharpCodeMatcher' cannot be used in netstandard 1.3");
|
||||
#endif
|
||||
try
|
||||
{
|
||||
return (bool)result;
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw new WireMockException($"Unable to cast result '{result}' to bool");
|
||||
}
|
||||
}
|
||||
|
||||
private string GetSourceForIsMatchWithString(string pattern, bool isMatchWithString)
|
||||
{
|
||||
string template = isMatchWithString ? TemplateForIsMatchWithString : TemplateForIsMatchWithDynamic;
|
||||
return string.Format(template, string.Join(Environment.NewLine, _usings.Select(u => $"using {u};")), pattern);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IStringMatcher.GetPatterns"/>
|
||||
public string[] GetPatterns()
|
||||
{
|
||||
return _patterns;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IMatcher.Name"/>
|
||||
public string Name => "CSharpCodeMatcher";
|
||||
}
|
||||
}
|
||||
73
src/WireMock.Net/Matchers/ContentTypeMatcher.cs
Normal file
73
src/WireMock.Net/Matchers/ContentTypeMatcher.cs
Normal file
@@ -0,0 +1,73 @@
|
||||
using System.Net.Http.Headers;
|
||||
using JetBrains.Annotations;
|
||||
|
||||
namespace WireMock.Matchers
|
||||
{
|
||||
/// <summary>
|
||||
/// ContentTypeMatcher which accepts also all charsets
|
||||
/// </summary>
|
||||
/// <seealso cref="RegexMatcher" />
|
||||
public class ContentTypeMatcher : WildcardMatcher
|
||||
{
|
||||
private readonly string[] _patterns;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ContentTypeMatcher"/> class.
|
||||
/// </summary>
|
||||
/// <param name="pattern">The pattern.</param>
|
||||
/// <param name="ignoreCase">IgnoreCase (default false)</param>
|
||||
public ContentTypeMatcher([NotNull] string pattern, bool ignoreCase = false) : this(new[] { pattern }, ignoreCase)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ContentTypeMatcher"/> class.
|
||||
/// </summary>
|
||||
/// <param name="matchBehaviour">The match behaviour.</param>
|
||||
/// <param name="pattern">The pattern.</param>
|
||||
/// <param name="ignoreCase">IgnoreCase (default false)</param>
|
||||
public ContentTypeMatcher(MatchBehaviour matchBehaviour, [NotNull] string pattern, bool ignoreCase = false) : this(matchBehaviour, new[] { pattern }, ignoreCase)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ContentTypeMatcher"/> class.
|
||||
/// </summary>
|
||||
/// <param name="patterns">The patterns.</param>
|
||||
/// <param name="ignoreCase">IgnoreCase (default false)</param>
|
||||
public ContentTypeMatcher([NotNull] string[] patterns, bool ignoreCase = false) : this(MatchBehaviour.AcceptOnMatch, patterns, ignoreCase)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ContentTypeMatcher"/> class.
|
||||
/// </summary>
|
||||
/// <param name="matchBehaviour">The match behaviour.</param>
|
||||
/// <param name="patterns">The patterns.</param>
|
||||
/// <param name="ignoreCase">IgnoreCase (default false)</param>
|
||||
public ContentTypeMatcher(MatchBehaviour matchBehaviour, [NotNull] string[] patterns, bool ignoreCase = false) : base(matchBehaviour, patterns, ignoreCase)
|
||||
{
|
||||
_patterns = patterns;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="RegexMatcher.IsMatch"/>
|
||||
public override double IsMatch(string input)
|
||||
{
|
||||
if (string.IsNullOrEmpty(input) || !MediaTypeHeaderValue.TryParse(input, out MediaTypeHeaderValue contentType))
|
||||
{
|
||||
return MatchBehaviourHelper.Convert(MatchBehaviour, MatchScores.Mismatch);
|
||||
}
|
||||
|
||||
return base.IsMatch(contentType.MediaType);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IStringMatcher.GetPatterns"/>
|
||||
public override string[] GetPatterns()
|
||||
{
|
||||
return _patterns;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IMatcher.Name"/>
|
||||
public override string Name => "ContentTypeMatcher";
|
||||
}
|
||||
}
|
||||
@@ -93,10 +93,7 @@ namespace WireMock.Matchers
|
||||
|
||||
private double IsMatch(JToken jtoken)
|
||||
{
|
||||
// Wrap in array if needed
|
||||
JToken tokenOrArray = jtoken is JArray ? jtoken : new JArray(jtoken);
|
||||
|
||||
return MatchScores.ToScore(_patterns.Select(pattern => tokenOrArray.SelectToken(pattern) != null));
|
||||
return MatchScores.ToScore(_patterns.Select(pattern => jtoken.SelectToken(pattern) != null));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,8 @@
|
||||
using System.Linq;
|
||||
using JetBrains.Annotations;
|
||||
using JetBrains.Annotations;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System.Linq;
|
||||
using WireMock.Util;
|
||||
using WireMock.Validation;
|
||||
|
||||
namespace WireMock.Matchers
|
||||
@@ -93,7 +94,7 @@ namespace WireMock.Matchers
|
||||
break;
|
||||
|
||||
case string stringValue:
|
||||
jtokenValue = JToken.Parse(stringValue);
|
||||
jtokenValue = JsonUtils.Parse(stringValue);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
@@ -9,8 +9,9 @@ namespace WireMock.Matchers
|
||||
/// <summary>
|
||||
/// System.Linq.Dynamic.Core Expression Matcher
|
||||
/// </summary>
|
||||
/// <inheritdoc cref="IObjectMatcher"/>
|
||||
/// <inheritdoc cref="IStringMatcher"/>
|
||||
public class LinqMatcher : IStringMatcher
|
||||
public class LinqMatcher : IObjectMatcher, IStringMatcher
|
||||
{
|
||||
private readonly string[] _patterns;
|
||||
|
||||
@@ -117,7 +118,6 @@ namespace WireMock.Matchers
|
||||
}
|
||||
|
||||
return MatchBehaviourHelper.Convert(MatchBehaviour, match);
|
||||
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IStringMatcher.GetPatterns"/>
|
||||
|
||||
@@ -71,7 +71,7 @@ namespace WireMock.Matchers
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IStringMatcher.IsMatch"/>
|
||||
public double IsMatch(string input)
|
||||
public virtual double IsMatch(string input)
|
||||
{
|
||||
double match = MatchScores.Mismatch;
|
||||
if (input != null)
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace WireMock.Owin
|
||||
|
||||
IStringMatcher AuthorizationMatcher { get; set; }
|
||||
|
||||
bool AllowPartialMapping { get; set; }
|
||||
bool? AllowPartialMapping { get; set; }
|
||||
|
||||
ConcurrentDictionary<Guid, IMapping> Mappings { get; }
|
||||
|
||||
@@ -37,5 +37,7 @@ namespace WireMock.Owin
|
||||
Action<IAppBuilder> PostWireMockMiddlewareInit { get; set; }
|
||||
|
||||
IFileSystemHandler FileSystemHandler { get; set; }
|
||||
|
||||
bool? AllowBodyForAllHttpMethods { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,8 @@ namespace WireMock.Owin.Mappers
|
||||
/// MapAsync IRequest to RequestMessage
|
||||
/// </summary>
|
||||
/// <param name="request">The OwinRequest/HttpRequest</param>
|
||||
/// <param name="options">The WireMockMiddlewareOptions</param>
|
||||
/// <returns>RequestMessage</returns>
|
||||
Task<RequestMessage> MapAsync(IRequest request);
|
||||
Task<RequestMessage> MapAsync(IRequest request, IWireMockMiddlewareOptions options);
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,7 @@ namespace WireMock.Owin.Mappers
|
||||
internal class OwinRequestMapper : IOwinRequestMapper
|
||||
{
|
||||
/// <inheritdoc cref="IOwinRequestMapper.MapAsync"/>
|
||||
public async Task<RequestMessage> MapAsync(IRequest request)
|
||||
public async Task<RequestMessage> MapAsync(IRequest request, IWireMockMiddlewareOptions options)
|
||||
{
|
||||
(UrlDetails urldetails, string clientIP) = ParseRequest(request);
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace WireMock.Owin.Mappers
|
||||
}
|
||||
|
||||
BodyData body = null;
|
||||
if (request.Body != null && BodyParser.ShouldParseBody(method))
|
||||
if (request.Body != null && BodyParser.ShouldParseBody(method, options.AllowBodyForAllHttpMethods == true))
|
||||
{
|
||||
body = await BodyParser.Parse(request.Body, request.ContentType);
|
||||
}
|
||||
|
||||
@@ -4,8 +4,11 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
using RandomDataGenerator.FieldOptions;
|
||||
using RandomDataGenerator.Randomizers;
|
||||
using WireMock.Handlers;
|
||||
using WireMock.Http;
|
||||
using WireMock.ResponseBuilders;
|
||||
using WireMock.Util;
|
||||
using WireMock.Validation;
|
||||
#if !USE_ASPNETCORE
|
||||
@@ -22,6 +25,8 @@ namespace WireMock.Owin.Mappers
|
||||
/// </summary>
|
||||
public class OwinResponseMapper : IOwinResponseMapper
|
||||
{
|
||||
private readonly IRandomizerNumber<double> _randomizerDouble = RandomizerFactory.GetRandomizer(new FieldOptionsDouble { Min = 0, Max = 1 });
|
||||
private readonly IRandomizerBytes _randomizerBytes = RandomizerFactory.GetRandomizer(new FieldOptionsBytes { Min = 100, Max = 200 });
|
||||
private readonly IFileSystemHandler _fileSystemHandler;
|
||||
private readonly Encoding _utf8NoBom = new UTF8Encoding(false);
|
||||
|
||||
@@ -53,8 +58,43 @@ namespace WireMock.Owin.Mappers
|
||||
return;
|
||||
}
|
||||
|
||||
response.StatusCode = responseMessage.StatusCode;
|
||||
byte[] bytes;
|
||||
switch (responseMessage.FaultType)
|
||||
{
|
||||
case FaultType.EMPTY_RESPONSE:
|
||||
bytes = IsFault(responseMessage) ? new byte[0] : GetNormalBody(responseMessage);
|
||||
break;
|
||||
|
||||
case FaultType.MALFORMED_RESPONSE_CHUNK:
|
||||
bytes = GetNormalBody(responseMessage) ?? new byte[0];
|
||||
if (IsFault(responseMessage))
|
||||
{
|
||||
bytes = bytes.Take(bytes.Length / 2).Union(_randomizerBytes.Generate()).ToArray();
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
bytes = GetNormalBody(responseMessage);
|
||||
break;
|
||||
}
|
||||
|
||||
response.StatusCode = responseMessage.StatusCode;
|
||||
SetResponseHeaders(responseMessage, response);
|
||||
|
||||
if (bytes != null)
|
||||
{
|
||||
await response.Body.WriteAsync(bytes, 0, bytes.Length);
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsFault(ResponseMessage responseMessage)
|
||||
{
|
||||
return responseMessage.FaultPercentage == null || _randomizerDouble.Generate() <= responseMessage.FaultPercentage;
|
||||
}
|
||||
|
||||
private byte[] GetNormalBody(ResponseMessage responseMessage)
|
||||
{
|
||||
byte[] bytes = null;
|
||||
switch (responseMessage.BodyData?.DetectedBodyType)
|
||||
{
|
||||
@@ -63,7 +103,9 @@ namespace WireMock.Owin.Mappers
|
||||
break;
|
||||
|
||||
case BodyType.Json:
|
||||
Formatting formatting = responseMessage.BodyData.BodyAsJsonIndented == true ? Formatting.Indented : Formatting.None;
|
||||
Formatting formatting = responseMessage.BodyData.BodyAsJsonIndented == true
|
||||
? Formatting.Indented
|
||||
: Formatting.None;
|
||||
string jsonBody = JsonConvert.SerializeObject(responseMessage.BodyData.BodyAsJson, new JsonSerializerSettings { Formatting = formatting, NullValueHandling = NullValueHandling.Ignore });
|
||||
bytes = (responseMessage.BodyData.Encoding ?? _utf8NoBom).GetBytes(jsonBody);
|
||||
break;
|
||||
@@ -77,12 +119,7 @@ namespace WireMock.Owin.Mappers
|
||||
break;
|
||||
}
|
||||
|
||||
SetResponseHeaders(responseMessage, response);
|
||||
|
||||
if (bytes != null)
|
||||
{
|
||||
await response.Body.WriteAsync(bytes, 0, bytes.Length);
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
private void SetResponseHeaders(ResponseMessage responseMessage, IResponse response)
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace WireMock.Owin
|
||||
}
|
||||
}
|
||||
|
||||
if (_options.AllowPartialMapping)
|
||||
if (_options.AllowPartialMapping == true)
|
||||
{
|
||||
var partialMappings = mappings
|
||||
.Where(pm => (pm.Mapping.IsAdminInterface && pm.RequestMatchResult.IsPerfectMatch) || !pm.Mapping.IsAdminInterface)
|
||||
|
||||
@@ -69,7 +69,7 @@ namespace WireMock.Owin
|
||||
|
||||
private async Task InvokeInternal(IContext ctx)
|
||||
{
|
||||
var request = await _requestMapper.MapAsync(ctx.Request);
|
||||
var request = await _requestMapper.MapAsync(ctx.Request, _options);
|
||||
|
||||
bool logRequest = false;
|
||||
ResponseMessage response = null;
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace WireMock.Owin
|
||||
|
||||
public IStringMatcher AuthorizationMatcher { get; set; }
|
||||
|
||||
public bool AllowPartialMapping { get; set; }
|
||||
public bool? AllowPartialMapping { get; set; }
|
||||
|
||||
public ConcurrentDictionary<Guid, IMapping> Mappings { get; } = new ConcurrentDictionary<Guid, IMapping>();
|
||||
|
||||
@@ -39,5 +39,8 @@ namespace WireMock.Owin
|
||||
|
||||
/// <inheritdoc cref="IWireMockMiddlewareOptions.FileSystemHandler"/>
|
||||
public IFileSystemHandler FileSystemHandler { get; set; }
|
||||
|
||||
/// <inheritdoc cref="IWireMockMiddlewareOptions.AllowBodyForAllHttpMethods"/>
|
||||
public bool? AllowBodyForAllHttpMethods { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,14 @@
|
||||
using JetBrains.Annotations;
|
||||
using System;
|
||||
using WireMock.Matchers;
|
||||
using WireMock.Matchers.Request;
|
||||
|
||||
namespace WireMock.RequestBuilders
|
||||
{
|
||||
/// <summary>
|
||||
/// The BodyRequestBuilder interface.
|
||||
/// </summary>
|
||||
public interface IBodyRequestBuilder
|
||||
public interface IBodyRequestBuilder : IRequestMatcher
|
||||
{
|
||||
/// <summary>
|
||||
/// WithBody: IMatcher
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
using System;
|
||||
using JetBrains.Annotations;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using JetBrains.Annotations;
|
||||
using WireMock.Matchers;
|
||||
using WireMock.Matchers.Request;
|
||||
|
||||
namespace WireMock.RequestBuilders
|
||||
{
|
||||
/// <summary>
|
||||
/// The HeadersAndCookieRequestBuilder interface.
|
||||
/// </summary>
|
||||
public interface IHeadersAndCookiesRequestBuilder : IBodyRequestBuilder, IRequestMatcher, IParamsRequestBuilder
|
||||
public interface IHeadersAndCookiesRequestBuilder : IParamsRequestBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// WithHeader: matching based on name, pattern and matchBehaviour.
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace WireMock.RequestBuilders
|
||||
/// <summary>
|
||||
/// The ParamsRequestBuilder interface.
|
||||
/// </summary>
|
||||
public interface IParamsRequestBuilder
|
||||
public interface IParamsRequestBuilder : IBodyRequestBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// WithParam: matching on key only.
|
||||
|
||||
23
src/WireMock.Net/ResponseBuilders/FaultType.cs
Normal file
23
src/WireMock.Net/ResponseBuilders/FaultType.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
namespace WireMock.ResponseBuilders
|
||||
{
|
||||
/// <summary>
|
||||
/// The FaultType enumeration
|
||||
/// </summary>
|
||||
public enum FaultType
|
||||
{
|
||||
/// <summary>
|
||||
/// No Fault
|
||||
/// </summary>
|
||||
NONE,
|
||||
|
||||
/// <summary>
|
||||
/// Return a completely empty response.
|
||||
/// </summary>
|
||||
EMPTY_RESPONSE,
|
||||
|
||||
/// <summary>
|
||||
/// Send a defined status header, then garbage, then close the connection.
|
||||
/// </summary>
|
||||
MALFORMED_RESPONSE_CHUNK
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@ namespace WireMock.ResponseBuilders
|
||||
/// <summary>
|
||||
/// The BodyResponseBuilder interface.
|
||||
/// </summary>
|
||||
public interface IBodyResponseBuilder : ITransformResponseBuilder
|
||||
public interface IBodyResponseBuilder : IFaultResponseBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// WithBody : Create a ... response based on a string.
|
||||
|
||||
18
src/WireMock.Net/ResponseBuilders/IFaultRequestBuilder.cs
Normal file
18
src/WireMock.Net/ResponseBuilders/IFaultRequestBuilder.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using JetBrains.Annotations;
|
||||
|
||||
namespace WireMock.ResponseBuilders
|
||||
{
|
||||
/// <summary>
|
||||
/// The FaultRequestBuilder interface.
|
||||
/// </summary>
|
||||
public interface IFaultResponseBuilder : ITransformResponseBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// WithBody : Create a fault response.
|
||||
/// </summary>
|
||||
/// <param name="faultType">The FaultType.</param>
|
||||
/// <param name="percentage">The percentage when this fault should occur. When null, it's always.</param>
|
||||
/// <returns>A <see cref="IResponseBuilder"/>.</returns>
|
||||
IResponseBuilder WithFault(FaultType faultType, [CanBeNull] double? percentage = null);
|
||||
}
|
||||
}
|
||||
14
src/WireMock.Net/ResponseBuilders/Response.WithFault.cs
Normal file
14
src/WireMock.Net/ResponseBuilders/Response.WithFault.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
namespace WireMock.ResponseBuilders
|
||||
{
|
||||
public partial class Response
|
||||
{
|
||||
/// <inheritdoc cref="IFaultResponseBuilder.WithFault(FaultType, double?)"/>
|
||||
public IResponseBuilder WithFault(FaultType faultType, double? percentage = null)
|
||||
{
|
||||
ResponseMessage.FaultType = faultType;
|
||||
ResponseMessage.FaultPercentage = percentage;
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,7 @@ namespace WireMock.ResponseBuilders
|
||||
/// <summary>
|
||||
/// The Response.
|
||||
/// </summary>
|
||||
public class Response : IResponseBuilder
|
||||
public partial class Response : IResponseBuilder
|
||||
{
|
||||
private HttpClient _httpClientForProxy;
|
||||
|
||||
@@ -375,6 +375,7 @@ namespace WireMock.ResponseBuilders
|
||||
public async Task<ResponseMessage> ProvideResponseAsync(RequestMessage requestMessage, IFluentMockServerSettings settings)
|
||||
{
|
||||
Check.NotNull(requestMessage, nameof(requestMessage));
|
||||
Check.NotNull(settings, nameof(settings));
|
||||
|
||||
if (Delay != null)
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using WireMock.ResponseBuilders;
|
||||
using WireMock.Util;
|
||||
using WireMock.Validation;
|
||||
|
||||
@@ -35,6 +36,16 @@ namespace WireMock
|
||||
/// </summary>
|
||||
public BodyData BodyData { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The FaultType.
|
||||
/// </summary>
|
||||
public FaultType FaultType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Fault percentage.
|
||||
/// </summary>
|
||||
public double? FaultPercentage { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Adds the header.
|
||||
/// </summary>
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using WireMock.Admin.Mappings;
|
||||
using WireMock.Admin.Requests;
|
||||
using WireMock.Logging;
|
||||
using WireMock.ResponseBuilders;
|
||||
using WireMock.Util;
|
||||
|
||||
namespace WireMock.Serialization
|
||||
@@ -61,6 +62,12 @@ namespace WireMock.Serialization
|
||||
Headers = logEntry.ResponseMessage.Headers
|
||||
};
|
||||
|
||||
if (logEntry.ResponseMessage.FaultType != FaultType.NONE)
|
||||
{
|
||||
logResponseModel.FaultType = logEntry.ResponseMessage.FaultType.ToString();
|
||||
logResponseModel.FaultPercentage = logEntry.ResponseMessage.FaultPercentage;
|
||||
}
|
||||
|
||||
if (logEntry.ResponseMessage.BodyData != null)
|
||||
{
|
||||
logResponseModel.BodyOriginal = logEntry.ResponseMessage.BodyOriginal;
|
||||
|
||||
@@ -114,6 +114,7 @@ namespace WireMock.Serialization
|
||||
mappingModel.Response.UseTransformer = null;
|
||||
mappingModel.Response.BodyEncoding = null;
|
||||
mappingModel.Response.ProxyUrl = response.ProxyUrl;
|
||||
mappingModel.Response.Fault = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -161,6 +162,15 @@ namespace WireMock.Serialization
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (response.ResponseMessage.FaultType != FaultType.NONE)
|
||||
{
|
||||
mappingModel.Response.Fault = new FaultModel
|
||||
{
|
||||
Type = response.ResponseMessage.FaultType.ToString(),
|
||||
Percentage = response.ResponseMessage.FaultPercentage
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return mappingModel;
|
||||
|
||||
@@ -41,6 +41,14 @@ namespace WireMock.Serialization
|
||||
|
||||
switch (matcherName)
|
||||
{
|
||||
case "CSharpCodeMatcher":
|
||||
if (_settings.AllowCSharpCodeMatcher == true)
|
||||
{
|
||||
return new CSharpCodeMatcher(matchBehaviour, stringPatterns);
|
||||
}
|
||||
|
||||
throw new NotSupportedException("It's not allowed to use the 'CSharpCodeMatcher' because FluentMockServerSettings.AllowCSharpCodeMatcher is not set to 'true'.");
|
||||
|
||||
case "LinqMatcher":
|
||||
return new LinqMatcher(matchBehaviour, stringPatterns);
|
||||
|
||||
@@ -68,6 +76,9 @@ namespace WireMock.Serialization
|
||||
case "WildcardMatcher":
|
||||
return new WildcardMatcher(matchBehaviour, stringPatterns, matcher.IgnoreCase == true);
|
||||
|
||||
case "ContentTypeMatcher":
|
||||
return new ContentTypeMatcher(matchBehaviour, stringPatterns, matcher.IgnoreCase == true);
|
||||
|
||||
case "SimMetricsMatcher":
|
||||
SimMetricType type = SimMetricType.Levenstein;
|
||||
if (!string.IsNullOrEmpty(matcherType) && !Enum.TryParse(matcherType, out type))
|
||||
|
||||
@@ -39,9 +39,11 @@ namespace WireMock.Server
|
||||
private const string AdminRequests = "/__admin/requests";
|
||||
private const string AdminSettings = "/__admin/settings";
|
||||
private const string AdminScenarios = "/__admin/scenarios";
|
||||
private const string QueryParamReloadStaticMappings = "reloadStaticMappings";
|
||||
|
||||
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 RegexMatcher _adminRequestContentTypeJson = new ContentTypeMatcher(ContentTypeJson, true);
|
||||
private readonly RegexMatcher _adminMappingsGuidPathMatcher = new RegexMatcher(@"^\/__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(@"^\/__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 _jsonSerializerSettings = new JsonSerializerSettings
|
||||
{
|
||||
@@ -60,19 +62,19 @@ namespace WireMock.Server
|
||||
{
|
||||
// __admin/settings
|
||||
Given(Request.Create().WithPath(AdminSettings).UsingGet()).AtPriority(AdminPriority).RespondWith(new DynamicResponseProvider(SettingsGet));
|
||||
Given(Request.Create().WithPath(AdminSettings).UsingMethod("PUT", "POST").WithHeader(HttpKnownHeaderNames.ContentType, ContentTypeJson)).AtPriority(AdminPriority).RespondWith(new DynamicResponseProvider(SettingsUpdate));
|
||||
Given(Request.Create().WithPath(AdminSettings).UsingMethod("PUT", "POST").WithHeader(HttpKnownHeaderNames.ContentType, _adminRequestContentTypeJson)).AtPriority(AdminPriority).RespondWith(new DynamicResponseProvider(SettingsUpdate));
|
||||
|
||||
// __admin/mappings
|
||||
Given(Request.Create().WithPath(AdminMappings).UsingGet()).AtPriority(AdminPriority).RespondWith(new DynamicResponseProvider(MappingsGet));
|
||||
Given(Request.Create().WithPath(AdminMappings).UsingPost().WithHeader(HttpKnownHeaderNames.ContentType, ContentTypeJson)).AtPriority(AdminPriority).RespondWith(new DynamicResponseProvider(MappingsPost));
|
||||
Given(Request.Create().WithPath(AdminMappings).UsingPost().WithHeader(HttpKnownHeaderNames.ContentType, _adminRequestContentTypeJson)).AtPriority(AdminPriority).RespondWith(new DynamicResponseProvider(MappingsPost));
|
||||
Given(Request.Create().WithPath(AdminMappings).UsingDelete()).AtPriority(AdminPriority).RespondWith(new DynamicResponseProvider(MappingsDelete));
|
||||
|
||||
// __admin/mappings/reset
|
||||
Given(Request.Create().WithPath(AdminMappings + "/reset").UsingPost()).AtPriority(AdminPriority).RespondWith(new DynamicResponseProvider(MappingsDelete));
|
||||
Given(Request.Create().WithPath(AdminMappings + "/reset").UsingPost()).AtPriority(AdminPriority).RespondWith(new DynamicResponseProvider(MappingsReset));
|
||||
|
||||
// __admin/mappings/{guid}
|
||||
Given(Request.Create().WithPath(_adminMappingsGuidPathMatcher).UsingGet()).AtPriority(AdminPriority).RespondWith(new DynamicResponseProvider(MappingGet));
|
||||
Given(Request.Create().WithPath(_adminMappingsGuidPathMatcher).UsingPut().WithHeader(HttpKnownHeaderNames.ContentType, ContentTypeJson)).AtPriority(AdminPriority).RespondWith(new DynamicResponseProvider(MappingPut));
|
||||
Given(Request.Create().WithPath(_adminMappingsGuidPathMatcher).UsingPut().WithHeader(HttpKnownHeaderNames.ContentType, _adminRequestContentTypeJson)).AtPriority(AdminPriority).RespondWith(new DynamicResponseProvider(MappingPut));
|
||||
Given(Request.Create().WithPath(_adminMappingsGuidPathMatcher).UsingDelete()).AtPriority(AdminPriority).RespondWith(new DynamicResponseProvider(MappingDelete));
|
||||
|
||||
// __admin/mappings/save
|
||||
@@ -140,7 +142,7 @@ namespace WireMock.Server
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (string filename in _settings.FileSystemHandler.EnumerateFiles(folder).OrderBy(f => f))
|
||||
foreach (string filename in _settings.FileSystemHandler.EnumerateFiles(folder, _settings.WatchStaticMappingsInSubdirectories == true).OrderBy(f => f))
|
||||
{
|
||||
_settings.Logger.Info("Reading Static MappingFile : '{0}'", filename);
|
||||
|
||||
@@ -172,9 +174,14 @@ namespace WireMock.Server
|
||||
return;
|
||||
}
|
||||
|
||||
_settings.Logger.Info("Watching folder '{0}' for new, updated and deleted MappingFiles.", folder);
|
||||
bool includeSubdirectories = _settings.WatchStaticMappingsInSubdirectories == true;
|
||||
string includeSubdirectoriesText = includeSubdirectories ? " and Subdirectories" : string.Empty;
|
||||
|
||||
_settings.Logger.Info($"Watching folder '{folder}'{includeSubdirectoriesText} for new, updated and deleted MappingFiles.");
|
||||
|
||||
var watcher = new EnhancedFileSystemWatcher(folder, "*.json", EnhancedFileSystemWatcherTimeoutMs);
|
||||
watcher.IncludeSubdirectories = includeSubdirectories;
|
||||
|
||||
watcher.Created += (sender, args) =>
|
||||
{
|
||||
_settings.Logger.Info("MappingFile created : '{0}', reading file.", args.FullPath);
|
||||
@@ -266,7 +273,8 @@ namespace WireMock.Server
|
||||
|
||||
var responseMessage = await HttpClientHelper.SendAsync(_httpClientForProxy, requestMessage, proxyUriWithRequestPathAndQuery.AbsoluteUri);
|
||||
|
||||
if (settings.ProxyAndRecordSettings.SaveMapping || settings.ProxyAndRecordSettings.SaveMappingToFile)
|
||||
if (HttpStatusRangeParser.IsMatch(settings.ProxyAndRecordSettings.SaveMappingForStatusCodePattern, responseMessage.StatusCode) &&
|
||||
(settings.ProxyAndRecordSettings.SaveMapping || settings.ProxyAndRecordSettings.SaveMappingToFile))
|
||||
{
|
||||
var mapping = ToMapping(requestMessage, responseMessage, settings.ProxyAndRecordSettings.BlackListedHeaders ?? new string[] { }, settings.ProxyAndRecordSettings.BlackListedCookies ?? new string[] { });
|
||||
|
||||
@@ -337,7 +345,8 @@ namespace WireMock.Server
|
||||
AllowPartialMapping = _options.AllowPartialMapping,
|
||||
MaxRequestLogCount = _options.MaxRequestLogCount,
|
||||
RequestLogExpirationDuration = _options.RequestLogExpirationDuration,
|
||||
GlobalProcessingDelay = (int?)_options.RequestProcessingDelay?.TotalMilliseconds
|
||||
GlobalProcessingDelay = (int?)_options.RequestProcessingDelay?.TotalMilliseconds,
|
||||
AllowBodyForAllHttpMethods = _options.AllowBodyForAllHttpMethods
|
||||
};
|
||||
|
||||
return ToJson(model);
|
||||
@@ -359,6 +368,11 @@ namespace WireMock.Server
|
||||
_options.RequestProcessingDelay = TimeSpan.FromMilliseconds(settings.GlobalProcessingDelay.Value);
|
||||
}
|
||||
|
||||
if (settings.AllowBodyForAllHttpMethods != null)
|
||||
{
|
||||
_options.AllowBodyForAllHttpMethods = settings.AllowBodyForAllHttpMethods.Value;
|
||||
}
|
||||
|
||||
return ResponseMessageBuilder.Create("Settings updated");
|
||||
}
|
||||
#endregion Settings
|
||||
@@ -543,6 +557,24 @@ namespace WireMock.Server
|
||||
|
||||
return ResponseMessageBuilder.Create("Mappings deleted");
|
||||
}
|
||||
|
||||
private ResponseMessage MappingsReset(RequestMessage requestMessage)
|
||||
{
|
||||
ResetMappings();
|
||||
|
||||
ResetScenarios();
|
||||
|
||||
string message = "Mappings reset";
|
||||
if (requestMessage.Query.ContainsKey(QueryParamReloadStaticMappings) &&
|
||||
bool.TryParse(requestMessage.Query[QueryParamReloadStaticMappings].ToString(), out bool reloadStaticMappings)
|
||||
&& reloadStaticMappings)
|
||||
{
|
||||
ReadStaticMappings();
|
||||
message = $"{message} and static mappings reloaded";
|
||||
}
|
||||
|
||||
return ResponseMessageBuilder.Create(message);
|
||||
}
|
||||
#endregion Mappings
|
||||
|
||||
#region Request/{guid}
|
||||
@@ -812,6 +844,11 @@ namespace WireMock.Server
|
||||
responseBuilder = responseBuilder.WithBodyFromFile(responseModel.BodyAsFile);
|
||||
}
|
||||
|
||||
if (responseModel.Fault != null && Enum.TryParse(responseModel.Fault.Type, out FaultType faultType))
|
||||
{
|
||||
responseBuilder.WithFault(faultType, responseModel.Fault.Percentage);
|
||||
}
|
||||
|
||||
return responseBuilder;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,21 @@ namespace WireMock.Server
|
||||
[PublicAPI]
|
||||
public event NotifyCollectionChangedEventHandler LogEntriesChanged
|
||||
{
|
||||
add => _options.LogEntries.CollectionChanged += value;
|
||||
add
|
||||
{
|
||||
_options.LogEntries.CollectionChanged += (sender, eventRecordArgs) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
value(sender, eventRecordArgs);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
_options.Logger.Error("Error calling the LogEntriesChanged event handler: {0}", exception.Message);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
remove => _options.LogEntries.CollectionChanged -= value;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
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 JetBrains.Annotations;
|
||||
using Newtonsoft.Json;
|
||||
using WireMock.Admin.Mappings;
|
||||
using WireMock.Exceptions;
|
||||
using WireMock.Handlers;
|
||||
@@ -256,6 +256,12 @@ namespace WireMock.Server
|
||||
}
|
||||
}
|
||||
|
||||
if (settings.AllowBodyForAllHttpMethods == true)
|
||||
{
|
||||
_options.AllowBodyForAllHttpMethods = _settings.AllowBodyForAllHttpMethods;
|
||||
_settings.Logger.Info("AllowBodyForAllHttpMethods is set to {0}", _settings.AllowBodyForAllHttpMethods == true);
|
||||
}
|
||||
|
||||
if (settings.AllowPartialMapping == true)
|
||||
{
|
||||
AllowPartialMapping();
|
||||
|
||||
@@ -33,6 +33,10 @@ namespace WireMock.Settings
|
||||
[PublicAPI]
|
||||
public bool? WatchStaticMappings { get; set; }
|
||||
|
||||
/// <inheritdoc cref="IFluentMockServerSettings.WatchStaticMappingsInSubdirectories"/>
|
||||
[PublicAPI]
|
||||
public bool? WatchStaticMappingsInSubdirectories { get; set; }
|
||||
|
||||
/// <inheritdoc cref="IFluentMockServerSettings.ProxyAndRecordSettings"/>
|
||||
[PublicAPI]
|
||||
public IProxyAndRecordSettings ProxyAndRecordSettings { get; set; }
|
||||
@@ -89,5 +93,13 @@ namespace WireMock.Settings
|
||||
[PublicAPI]
|
||||
[JsonIgnore]
|
||||
public Action<IHandlebars, IFileSystemHandler> HandlebarsRegistrationCallback { get; set; }
|
||||
|
||||
/// <inheritdoc cref="IFluentMockServerSettings.AllowCSharpCodeMatcher"/>
|
||||
[PublicAPI]
|
||||
public bool? AllowCSharpCodeMatcher { get; set; }
|
||||
|
||||
/// <inheritdoc cref="IFluentMockServerSettings.AllowBodyForAllHttpMethods"/>
|
||||
[PublicAPI]
|
||||
public bool? AllowBodyForAllHttpMethods { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
using HandlebarsDotNet;
|
||||
using System;
|
||||
using HandlebarsDotNet;
|
||||
using JetBrains.Annotations;
|
||||
using System;
|
||||
using WireMock.Handlers;
|
||||
using WireMock.Logging;
|
||||
|
||||
@@ -42,6 +42,12 @@ namespace WireMock.Settings
|
||||
[PublicAPI]
|
||||
bool? WatchStaticMappings { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A value indicating whether subdirectories within the static mappings path should be monitored.
|
||||
/// </summary>
|
||||
[PublicAPI]
|
||||
bool? WatchStaticMappingsInSubdirectories { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets if the proxy and record settings.
|
||||
/// </summary>
|
||||
@@ -115,9 +121,21 @@ namespace WireMock.Settings
|
||||
IFileSystemHandler FileSystemHandler { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Action which can be used to add additional is Handlebar registrations. [Optional]
|
||||
/// Action which can be used to add additional Handlebars registrations. [Optional]
|
||||
/// </summary>
|
||||
[PublicAPI]
|
||||
Action<IHandlebars, IFileSystemHandler> HandlebarsRegistrationCallback { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Allow the usage of CSharpCodeMatcher (default is not allowed).
|
||||
/// </summary>
|
||||
[PublicAPI]
|
||||
bool? AllowCSharpCodeMatcher { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Allow a Body for all HTTP Methods. (default set to false).
|
||||
/// </summary>
|
||||
[PublicAPI]
|
||||
bool? AllowBodyForAllHttpMethods { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,6 @@
|
||||
namespace WireMock.Settings
|
||||
using JetBrains.Annotations;
|
||||
|
||||
namespace WireMock.Settings
|
||||
{
|
||||
/// <summary>
|
||||
/// IProxyAndRecordSettings
|
||||
@@ -16,7 +18,14 @@
|
||||
bool SaveMapping { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Save the mapping for each request/response to also file. (Note that SaveMapping must also be set to true.)
|
||||
/// Only save request/response to the internal Mappings if the status code is included in this pattern. (Note that SaveMapping must also be set to true.)
|
||||
/// The pattern can contain a single value like "200", but also ranges like "2xx", "100,300,600" or "100-299,6xx" are supported.
|
||||
/// </summary>
|
||||
[CanBeNull]
|
||||
string SaveMappingForStatusCodePattern { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Save the mapping for each request/response also to a file. (Note that SaveMapping must also be set to true.)
|
||||
/// </summary>
|
||||
bool SaveMappingToFile { get; set; }
|
||||
|
||||
|
||||
@@ -15,6 +15,10 @@ namespace WireMock.Settings
|
||||
[PublicAPI]
|
||||
public bool SaveMapping { get; set; } = true;
|
||||
|
||||
/// <inheritdoc cref="IProxyAndRecordSettings.SaveMappingForStatusCodePattern"/>
|
||||
[PublicAPI]
|
||||
public string SaveMappingForStatusCodePattern { get; set; } = "*";
|
||||
|
||||
/// <inheritdoc cref="IProxyAndRecordSettings.SaveMappingToFile"/>
|
||||
[PublicAPI]
|
||||
public bool SaveMappingToFile { get; set; } = true;
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using HandlebarsDotNet;
|
||||
using HandlebarsDotNet;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using WireMock.Util;
|
||||
using WireMock.Validation;
|
||||
|
||||
namespace WireMock.Transformers
|
||||
@@ -56,7 +57,7 @@ namespace WireMock.Transformers
|
||||
switch (arguments[0])
|
||||
{
|
||||
case string jsonAsString:
|
||||
valueToProcess = JObject.Parse(jsonAsString);
|
||||
valueToProcess = JsonUtils.Parse(jsonAsString);
|
||||
break;
|
||||
|
||||
case JObject jsonAsJObject:
|
||||
@@ -67,7 +68,7 @@ namespace WireMock.Transformers
|
||||
throw new NotSupportedException($"The value '{arguments[0]}' with type '{arguments[0]?.GetType()}' cannot be used in Handlebars JsonPath.");
|
||||
}
|
||||
|
||||
return (valueToProcess, (string) arguments[1]);
|
||||
return (valueToProcess, (string)arguments[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -45,6 +45,9 @@ namespace WireMock.Transformers
|
||||
break;
|
||||
}
|
||||
|
||||
responseMessage.FaultType = original.FaultType;
|
||||
responseMessage.FaultPercentage = original.FaultPercentage;
|
||||
|
||||
// Headers
|
||||
var newHeaders = new Dictionary<string, WireMockList<string>>();
|
||||
foreach (var header in original.Headers)
|
||||
|
||||
@@ -59,14 +59,19 @@ namespace WireMock.Util
|
||||
|
||||
private static readonly JsonSerializerSettings JsonSerializerSettings = new JsonSerializerSettings { DateParseHandling = DateParseHandling.None };
|
||||
|
||||
public static bool ShouldParseBody([CanBeNull] string method)
|
||||
public static bool ShouldParseBody([CanBeNull] string httpMethod, bool allowBodyForAllHttpMethods)
|
||||
{
|
||||
if (string.IsNullOrEmpty(method))
|
||||
if (string.IsNullOrEmpty(httpMethod))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (BodyAllowedForMethods.TryGetValue(method.ToUpper(), out bool allowed))
|
||||
if (allowBodyForAllHttpMethods)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (BodyAllowedForMethods.TryGetValue(httpMethod.ToUpper(), out bool allowed))
|
||||
{
|
||||
return allowed;
|
||||
}
|
||||
|
||||
71
src/WireMock.Net/Util/HttpStatusRangeParser.cs
Normal file
71
src/WireMock.Net/Util/HttpStatusRangeParser.cs
Normal file
@@ -0,0 +1,71 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace WireMock.Util
|
||||
{
|
||||
/// <summary>
|
||||
/// Based on https://github.com/tmenier/Flurl/blob/129565361e135e639f1d44a35a78aea4302ac6ca/src/Flurl.Http/HttpStatusRangeParser.cs
|
||||
/// </summary>
|
||||
internal static class HttpStatusRangeParser
|
||||
{
|
||||
/// <summary>
|
||||
/// Determines whether the specified pattern is match.
|
||||
/// </summary>
|
||||
/// <param name="pattern">The pattern. (Can be null, in that case it's allowed.)</param>
|
||||
/// <param name="httpStatusCode">The value.</param>
|
||||
/// <exception cref="ArgumentException"><paramref name="pattern"/> is invalid.</exception>
|
||||
public static bool IsMatch(string pattern, HttpStatusCode httpStatusCode)
|
||||
{
|
||||
return IsMatch(pattern, (int)httpStatusCode);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the specified pattern is match.
|
||||
/// </summary>
|
||||
/// <param name="pattern">The pattern. (Can be null, in that case it's allowed.)</param>
|
||||
/// <param name="httpStatusCode">The value.</param>
|
||||
/// <exception cref="ArgumentException"><paramref name="pattern"/> is invalid.</exception>
|
||||
public static bool IsMatch(string pattern, int httpStatusCode)
|
||||
{
|
||||
if (pattern == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
foreach (var range in pattern.Split(',').Select(p => p.Trim()))
|
||||
{
|
||||
switch (range)
|
||||
{
|
||||
case "":
|
||||
continue;
|
||||
|
||||
case "*":
|
||||
return true; // special case - allow everything
|
||||
}
|
||||
|
||||
string[] bounds = range.Split('-');
|
||||
int lower = 0;
|
||||
int upper = 0;
|
||||
|
||||
bool valid =
|
||||
bounds.Length <= 2 &&
|
||||
int.TryParse(Regex.Replace(bounds.First().Trim(), "[*xX]", "0"), out lower) &&
|
||||
int.TryParse(Regex.Replace(bounds.Last().Trim(), "[*xX]", "9"), out upper);
|
||||
|
||||
if (!valid)
|
||||
{
|
||||
throw new ArgumentException($"Invalid range pattern: \"{pattern}\". Examples of allowed patterns: \"400\", \"4xx\", \"300,400-403\", \"*\".");
|
||||
}
|
||||
|
||||
if (httpStatusCode >= lower && httpStatusCode <= upper)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@@ -8,6 +9,22 @@ namespace WireMock.Util
|
||||
{
|
||||
internal static class JsonUtils
|
||||
{
|
||||
private static readonly JsonSerializerSettings JsonSerializerSettings = new JsonSerializerSettings
|
||||
{
|
||||
DateParseHandling = DateParseHandling.None
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Load a Newtonsoft.Json.Linq.JObject from a string that contains JSON.
|
||||
/// Using : DateParseHandling = DateParseHandling.None
|
||||
/// </summary>
|
||||
/// <param name="json">A System.String that contains JSON.</param>
|
||||
/// <returns>A Newtonsoft.Json.Linq.JObject populated from the string that contains JSON.</returns>
|
||||
public static JObject Parse(string json)
|
||||
{
|
||||
return JsonConvert.DeserializeObject<JObject>(json, JsonSerializerSettings);
|
||||
}
|
||||
|
||||
public static T ParseJTokenToObject<T>(object value)
|
||||
{
|
||||
switch (value)
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
<Description>Lightweight Http Mocking Server for .Net, inspired by WireMock from the Java landscape.</Description>
|
||||
<AssemblyTitle>WireMock.Net</AssemblyTitle>
|
||||
<Authors>Stef Heyenrath</Authors>
|
||||
<!--<TargetFrameworks>net451;net452;net46;net461;netstandard1.3;netstandard2.0;netcoreapp2.1</TargetFrameworks>-->
|
||||
<TargetFrameworks>net451;net452;net46;net461;netstandard1.3;netstandard2.0</TargetFrameworks>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<AssemblyName>WireMock.Net</AssemblyName>
|
||||
@@ -11,14 +12,14 @@
|
||||
<PackageReleaseNotes>See CHANGELOG.md</PackageReleaseNotes>
|
||||
<PackageIconUrl>https://raw.githubusercontent.com/WireMock-Net/WireMock.Net/master/WireMock.Net-Logo.png</PackageIconUrl>
|
||||
<PackageProjectUrl>https://github.com/WireMock-Net/WireMock.Net</PackageProjectUrl>
|
||||
<PackageLicenseUrl>https://raw.githubusercontent.com/WireMock-Net/WireMock.Net/master/LICENSE</PackageLicenseUrl>
|
||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||
<RepositoryType>git</RepositoryType>
|
||||
<RepositoryUrl>https://github.com/WireMock-Net/WireMock.Net</RepositoryUrl>
|
||||
<ApplicationIcon>../../WireMock.Net-Logo.ico</ApplicationIcon>
|
||||
<RootNamespace>WireMock</RootNamespace>
|
||||
<DebugType>full</DebugType>
|
||||
<!--<DebugType>full</DebugType>
|
||||
<IncludeSource>True</IncludeSource>
|
||||
<IncludeSymbols>True</IncludeSymbols>
|
||||
<IncludeSymbols>True</IncludeSymbols>-->
|
||||
<ProjectGuid>{D3804228-91F4-4502-9595-39584E5A01AD}</ProjectGuid>
|
||||
<PublishRepositoryUrl>true</PublishRepositoryUrl>
|
||||
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
|
||||
@@ -31,6 +32,13 @@
|
||||
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
|
||||
</PropertyGroup>
|
||||
|
||||
<!--<ItemGroup>
|
||||
<None Include="WireMock.Net-Logo.png" Pack="true" PackagePath="../../"/>
|
||||
</ItemGroup>-->
|
||||
|
||||
<!--https://github.com/aspnet/RoslynCodeDomProvider/issues/51-->
|
||||
<Target Name="CheckIfShouldKillVBCSCompiler" />
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
|
||||
<PathMap>$(MSBuildProjectDirectory)=/</PathMap>
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
@@ -40,20 +48,30 @@
|
||||
<DefineConstants>NETSTANDARD;USE_ASPNETCORE</DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(TargetFramework)' == 'netcoreapp2.1' or '$(TargetFramework)' == 'netcoreapp2.2'">
|
||||
<DefineConstants>USE_ASPNETCORE</DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(TargetFramework)' == 'net461'">
|
||||
<DefineConstants>USE_ASPNETCORE;NET46</DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Remove="RequestBuilders\Request.WithFault.cs" />
|
||||
<Compile Remove="Util\CloneUtils.cs" />
|
||||
<Compile Remove="Util\IndexableDictionary.cs" />
|
||||
<Compile Remove="Util\NamedReaderWriterLocker.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="ResponseBuilders\Response.WithFault.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="JetBrains.Annotations" Version="2018.2.1">
|
||||
<PrivateAssets>All</PrivateAssets>
|
||||
</PackageReference>
|
||||
<!--<PackageReference Include="Microsoft.CSharp" Version="4.5.0" />-->
|
||||
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
|
||||
<PackageReference Include="SimMetrics.Net" Version="1.0.5" />
|
||||
<PackageReference Include="RestEase" Version="1.4.7" />
|
||||
@@ -62,7 +80,7 @@
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.0.12" />
|
||||
<PackageReference Include="RandomDataGenerator.Net" Version="1.0.8" />
|
||||
<PackageReference Include="RandomDataGenerator.Net" Version="1.0.10" />
|
||||
<PackageReference Include="JmesPath.Net" Version="1.0.125" />
|
||||
<!--<PackageReference Include="CloneExtensionsEx" Version="1.0.2" />-->
|
||||
<!--<PackageReference Include="FastDeepCloner" Version="1.2.5" />-->
|
||||
@@ -86,6 +104,7 @@
|
||||
|
||||
<PackageReference Include="Microsoft.AspNet.WebApi.OwinSelfHost" Version="5.2.6" />
|
||||
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
|
||||
<PackageReference Include="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" Version="2.0.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition=" '$(TargetFramework)' == 'net452' ">
|
||||
@@ -94,6 +113,7 @@
|
||||
|
||||
<PackageReference Include="Microsoft.AspNet.WebApi.OwinSelfHost" Version="5.2.6" />
|
||||
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
|
||||
<PackageReference Include="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" Version="2.0.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition=" '$(TargetFramework)' == 'net46' ">
|
||||
@@ -103,10 +123,12 @@
|
||||
<PackageReference Include="Microsoft.Owin.Hosting" Version="4.0.0" />
|
||||
<PackageReference Include="System.Net.Http" Version="4.3.3" />
|
||||
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
|
||||
<PackageReference Include="CS-Script" Version="3.29.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition=" '$(TargetFramework)' == 'net461' ">
|
||||
<PackageReference Include="Microsoft.AspNetCore" Version="2.1.2" />
|
||||
<PackageReference Include="CS-Script" Version="3.29.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard1.3' ">
|
||||
@@ -117,7 +139,8 @@
|
||||
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' ">
|
||||
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0'">
|
||||
<PackageReference Include="Microsoft.AspNetCore" Version="2.1.4" />
|
||||
<PackageReference Include="CS-Script.Core" Version="1.1.1" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -171,7 +171,7 @@ namespace WireMock.Net.Tests
|
||||
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.EnumerateFiles(It.IsAny<string>())).Returns(new string[0]);
|
||||
staticMappingHandlerMock.Setup(m => m.EnumerateFiles(It.IsAny<string>(), It.IsAny<bool>())).Returns(new string[0]);
|
||||
|
||||
var server = FluentMockServer.Start(new FluentMockServerSettings
|
||||
{
|
||||
@@ -184,7 +184,7 @@ namespace WireMock.Net.Tests
|
||||
// Assert and Verify
|
||||
staticMappingHandlerMock.Verify(m => m.GetMappingFolder(), Times.Once);
|
||||
staticMappingHandlerMock.Verify(m => m.FolderExists("folder"), Times.Once);
|
||||
staticMappingHandlerMock.Verify(m => m.EnumerateFiles("folder"), Times.Once);
|
||||
staticMappingHandlerMock.Verify(m => m.EnumerateFiles("folder", false), Times.Once);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
||||
@@ -116,7 +116,25 @@ namespace WireMock.Net.Tests
|
||||
|
||||
// Assert
|
||||
var options = server.GetPrivateFieldValue<IWireMockMiddlewareOptions>("_options");
|
||||
Check.That(options.AllowPartialMapping).IsTrue();
|
||||
Check.That(options.AllowPartialMapping).Equals(true);
|
||||
|
||||
// Verify
|
||||
_loggerMock.Verify(l => l.Info(It.IsAny<string>(), It.IsAny<bool>()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FluentMockServer_FluentMockServerSettings_AllowBodyForAllHttpMethods()
|
||||
{
|
||||
// Assign and Act
|
||||
var server = FluentMockServer.Start(new FluentMockServerSettings
|
||||
{
|
||||
Logger = _loggerMock.Object,
|
||||
AllowBodyForAllHttpMethods = true
|
||||
});
|
||||
|
||||
// Assert
|
||||
var options = server.GetPrivateFieldValue<IWireMockMiddlewareOptions>("_options");
|
||||
Check.That(options.AllowBodyForAllHttpMethods).Equals(true);
|
||||
|
||||
// Verify
|
||||
_loggerMock.Verify(l => l.Info(It.IsAny<string>(), It.IsAny<bool>()));
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
using NFluent;
|
||||
using System;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Threading.Tasks;
|
||||
using NFluent;
|
||||
using WireMock.RequestBuilders;
|
||||
using WireMock.ResponseBuilders;
|
||||
using WireMock.Server;
|
||||
@@ -187,7 +188,7 @@ namespace WireMock.Net.Tests
|
||||
var server = FluentMockServer.Start();
|
||||
|
||||
server
|
||||
.Given(Request.Create().WithBody((byte[] bodyBytes) => bodyBytes != null))
|
||||
.Given(Request.Create().WithBody((byte[] bodyBytes) => bodyBytes != null))
|
||||
.AtPriority(0)
|
||||
.RespondWith(Response.Create().WithStatusCode(400));
|
||||
server
|
||||
@@ -203,7 +204,7 @@ namespace WireMock.Net.Tests
|
||||
// Assert
|
||||
Check.That(response.StatusCode).Equals(HttpStatusCode.OK);
|
||||
}
|
||||
|
||||
|
||||
[Theory]
|
||||
[InlineData("POST")]
|
||||
[InlineData("PUT")]
|
||||
@@ -233,5 +234,38 @@ namespace WireMock.Net.Tests
|
||||
// Assert
|
||||
Check.That(response.StatusCode).Equals(HttpStatusCode.OK);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("application/json")]
|
||||
[InlineData("application/json; charset=ascii")]
|
||||
[InlineData("application/json; charset=utf-8")]
|
||||
[InlineData("application/json; charset=UTF-8")]
|
||||
public async Task WireMockServer_Should_AcceptPostMappingsWithContentTypeJsonAndAnyCharset(string contentType)
|
||||
{
|
||||
// Arrange
|
||||
string message = @"{
|
||||
""request"": {
|
||||
""method"": ""GET"",
|
||||
""url"": ""/some/thing""
|
||||
},
|
||||
""response"": {
|
||||
""status"": 200,
|
||||
""body"": ""Hello world!"",
|
||||
""headers"": {
|
||||
""Content-Type"": ""text/plain""
|
||||
}
|
||||
}
|
||||
}";
|
||||
var stringContent = new StringContent(message);
|
||||
stringContent.Headers.ContentType = MediaTypeHeaderValue.Parse(contentType);
|
||||
var server = FluentMockServer.StartWithAdminInterface();
|
||||
|
||||
// Act
|
||||
var response = await new HttpClient().PostAsync($"{server.Urls[0]}/__admin/mappings", stringContent);
|
||||
|
||||
// Assert
|
||||
Check.That(response.StatusCode).Equals(HttpStatusCode.Created);
|
||||
Check.That(await response.Content.ReadAsStringAsync()).Contains("Mapping added");
|
||||
}
|
||||
}
|
||||
}
|
||||
92
test/WireMock.Net.Tests/Matchers/CSharpCodeMatcherTests.cs
Normal file
92
test/WireMock.Net.Tests/Matchers/CSharpCodeMatcherTests.cs
Normal file
@@ -0,0 +1,92 @@
|
||||
using NFluent;
|
||||
using WireMock.Matchers;
|
||||
using Xunit;
|
||||
|
||||
namespace WireMock.Net.Tests.Matchers
|
||||
{
|
||||
public class CSharpCodeMatcherTests
|
||||
{
|
||||
[Fact]
|
||||
public void CSharpCodeMatcher_For_String_SinglePattern_IsMatch_Positive()
|
||||
{
|
||||
// Assign
|
||||
string input = "x";
|
||||
|
||||
// Act
|
||||
var matcher = new CSharpCodeMatcher("return it == \"x\";");
|
||||
|
||||
// Assert
|
||||
Check.That(matcher.IsMatch(input)).IsEqualTo(1.0d);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CSharpCodeMatcher_For_String_IsMatch_Negative()
|
||||
{
|
||||
// Assign
|
||||
string input = "y";
|
||||
|
||||
// Act
|
||||
var matcher = new CSharpCodeMatcher("return it == \"x\";");
|
||||
|
||||
// Assert
|
||||
Check.That(matcher.IsMatch(input)).IsEqualTo(0.0d);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CSharpCodeMatcher_For_String_IsMatch_RejectOnMatch()
|
||||
{
|
||||
// Assign
|
||||
string input = "x";
|
||||
|
||||
// Act
|
||||
var matcher = new CSharpCodeMatcher(MatchBehaviour.RejectOnMatch, "return it == \"x\";");
|
||||
|
||||
// Assert
|
||||
Check.That(matcher.IsMatch(input)).IsEqualTo(0.0d);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CSharpCodeMatcher_For_Object_IsMatch()
|
||||
{
|
||||
// Assign
|
||||
var input = new
|
||||
{
|
||||
Id = 9,
|
||||
Name = "Test"
|
||||
};
|
||||
|
||||
// Act
|
||||
var matcher = new CSharpCodeMatcher("return it.Id > 1 && it.Name == \"Test\";");
|
||||
double match = matcher.IsMatch(input);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(1.0, match);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CSharpCodeMatcher_GetName()
|
||||
{
|
||||
// Assign
|
||||
var matcher = new CSharpCodeMatcher("x");
|
||||
|
||||
// Act
|
||||
string name = matcher.Name;
|
||||
|
||||
// Assert
|
||||
Check.That(name).Equals("CSharpCodeMatcher");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CSharpCodeMatcher_GetPatterns()
|
||||
{
|
||||
// Assign
|
||||
var matcher = new CSharpCodeMatcher("x");
|
||||
|
||||
// Act
|
||||
string[] patterns = matcher.GetPatterns();
|
||||
|
||||
// Assert
|
||||
Check.That(patterns).ContainsExactly("x");
|
||||
}
|
||||
}
|
||||
}
|
||||
58
test/WireMock.Net.Tests/Matchers/ContentTypeMatcherTests.cs
Normal file
58
test/WireMock.Net.Tests/Matchers/ContentTypeMatcherTests.cs
Normal file
@@ -0,0 +1,58 @@
|
||||
using NFluent;
|
||||
using WireMock.Matchers;
|
||||
using Xunit;
|
||||
|
||||
namespace WireMock.Net.Tests.Matchers
|
||||
{
|
||||
public class ContentTypeMatcherTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData("application/json")]
|
||||
[InlineData("application/json; charset=ascii")]
|
||||
[InlineData("application/json; charset=utf-8")]
|
||||
[InlineData("application/json; charset=UTF-8")]
|
||||
public void ContentTypeMatcher_IsMatchWithIgnoreCaseFalse_Positive(string contentType)
|
||||
{
|
||||
var matcher = new ContentTypeMatcher("application/json");
|
||||
Check.That(matcher.IsMatch(contentType)).IsEqualTo(1.0d);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("application/json")]
|
||||
[InlineData("application/JSON")]
|
||||
[InlineData("application/json; CharSet=ascii")]
|
||||
[InlineData("application/json; charset=utf-8")]
|
||||
[InlineData("application/json; charset=UTF-8")]
|
||||
public void ContentTypeMatcher_IsMatchWithIgnoreCaseTrue_Positive(string contentType)
|
||||
{
|
||||
var matcher = new ContentTypeMatcher("application/json", true);
|
||||
Check.That(matcher.IsMatch(contentType)).IsEqualTo(1.0d);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ContentTypeMatcher_GetName()
|
||||
{
|
||||
// Assign
|
||||
var matcher = new ContentTypeMatcher("x");
|
||||
|
||||
// Act
|
||||
string name = matcher.Name;
|
||||
|
||||
// Assert
|
||||
Check.That(name).Equals("ContentTypeMatcher");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ContentTypeMatcher_GetPatterns()
|
||||
{
|
||||
// Assign
|
||||
var matcher = new ContentTypeMatcher("x");
|
||||
|
||||
// Act
|
||||
string[] patterns = matcher.GetPatterns();
|
||||
|
||||
// Assert
|
||||
Check.That(patterns).ContainsExactly("x");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -192,5 +192,22 @@ namespace WireMock.Net.Tests.Matchers
|
||||
// Assert
|
||||
Assert.Equal(0.0, match);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void JsonMatcher_IsMatch_JObjectWithDateTimeOffsetAsString()
|
||||
{
|
||||
// Assign
|
||||
var matcher = new JsonMatcher("{ \"preferredAt\" : \"2019-11-21T10:32:53.2210009+00:00\" }");
|
||||
|
||||
// Act
|
||||
var jobject = new JObject
|
||||
{
|
||||
{ "preferredAt", new JValue("2019-11-21T10:32:53.2210009+00:00") }
|
||||
};
|
||||
double match = matcher.IsMatch(jobject);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(1.0, match);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,16 +5,48 @@ using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Moq;
|
||||
using NFluent;
|
||||
using WireMock.Logging;
|
||||
using WireMock.RequestBuilders;
|
||||
using WireMock.ResponseBuilders;
|
||||
using WireMock.Server;
|
||||
using WireMock.Settings;
|
||||
using Xunit;
|
||||
|
||||
namespace WireMock.Net.Tests
|
||||
{
|
||||
public class ObservableLogEntriesTest
|
||||
{
|
||||
[Fact]
|
||||
public async void FluentMockServer_LogEntriesChanged_WithException_Should_LogError()
|
||||
{
|
||||
// Assign
|
||||
string path = $"/log_{Guid.NewGuid()}";
|
||||
var loggerMock = new Mock<IWireMockLogger>();
|
||||
loggerMock.Setup(l => l.Error(It.IsAny<string>(), It.IsAny<object[]>()));
|
||||
var settings = new FluentMockServerSettings
|
||||
{
|
||||
Logger = loggerMock.Object
|
||||
};
|
||||
var server = FluentMockServer.Start(settings);
|
||||
|
||||
server
|
||||
.Given(Request.Create()
|
||||
.WithPath(path)
|
||||
.UsingGet())
|
||||
.RespondWith(Response.Create()
|
||||
.WithBody(@"{ msg: ""Hello world!""}"));
|
||||
|
||||
server.LogEntriesChanged += (sender, args) => throw new Exception();
|
||||
|
||||
// Act
|
||||
await new HttpClient().GetAsync($"http://localhost:{server.Ports[0]}{path}");
|
||||
|
||||
// Assert
|
||||
loggerMock.Verify(l => l.Error(It.IsAny<string>(), It.IsAny<object[]>()), Times.Once);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async void FluentMockServer_LogEntriesChanged()
|
||||
{
|
||||
|
||||
@@ -6,6 +6,7 @@ using System.Threading.Tasks;
|
||||
using System.Threading;
|
||||
using WireMock.Handlers;
|
||||
using WireMock.Owin.Mappers;
|
||||
using WireMock.ResponseBuilders;
|
||||
using WireMock.Util;
|
||||
#if NET452
|
||||
using Microsoft.Owin;
|
||||
@@ -97,7 +98,7 @@ namespace WireMock.Net.Tests.Owin.Mappers
|
||||
public async Task OwinResponseMapper_MapAsync_Body()
|
||||
{
|
||||
// Arrange
|
||||
string body = "abc";
|
||||
string body = "abcd";
|
||||
var responseMessage = new ResponseMessage
|
||||
{
|
||||
Headers = new Dictionary<string, WireMockList<string>>(),
|
||||
@@ -108,7 +109,7 @@ namespace WireMock.Net.Tests.Owin.Mappers
|
||||
await _sut.MapAsync(responseMessage, _responseMock.Object);
|
||||
|
||||
// Assert
|
||||
_stream.Verify(s => s.WriteAsync(new byte[] { 97, 98, 99 }, 0, 3, It.IsAny<CancellationToken>()), Times.Once);
|
||||
_stream.Verify(s => s.WriteAsync(new byte[] { 97, 98, 99, 100 }, 0, 4, It.IsAny<CancellationToken>()), Times.Once);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -167,5 +168,47 @@ namespace WireMock.Net.Tests.Owin.Mappers
|
||||
_headers.Verify(h => h.TryGetValue("h", out v), Times.Once);
|
||||
#endif
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task OwinResponseMapper_MapAsync_WithFault_EMPTY_RESPONSE()
|
||||
{
|
||||
// Arrange
|
||||
string body = "abc";
|
||||
var responseMessage = new ResponseMessage
|
||||
{
|
||||
Headers = new Dictionary<string, WireMockList<string>>(),
|
||||
BodyData = new BodyData { DetectedBodyType = BodyType.String, BodyAsString = body },
|
||||
FaultType = FaultType.EMPTY_RESPONSE
|
||||
};
|
||||
|
||||
// Act
|
||||
await _sut.MapAsync(responseMessage, _responseMock.Object);
|
||||
|
||||
// Assert
|
||||
_stream.Verify(s => s.WriteAsync(new byte[0], 0, 0, It.IsAny<CancellationToken>()), Times.Once);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("abcd", BodyType.String)]
|
||||
[InlineData("", BodyType.String)]
|
||||
[InlineData(null, BodyType.None)]
|
||||
public async Task OwinResponseMapper_MapAsync_WithFault_MALFORMED_RESPONSE_CHUNK(string body, BodyType detected)
|
||||
{
|
||||
// Arrange
|
||||
var responseMessage = new ResponseMessage
|
||||
{
|
||||
Headers = new Dictionary<string, WireMockList<string>>(),
|
||||
BodyData = new BodyData { DetectedBodyType = detected, BodyAsString = body },
|
||||
StatusCode = 100,
|
||||
FaultType = FaultType.MALFORMED_RESPONSE_CHUNK
|
||||
};
|
||||
|
||||
// Act
|
||||
await _sut.MapAsync(responseMessage, _responseMock.Object);
|
||||
|
||||
// Assert
|
||||
_responseMock.VerifySet(r => r.StatusCode = 100, Times.Once);
|
||||
_stream.Verify(s => s.WriteAsync(It.IsAny<byte[]>(), 0, It.Is<int>(count => count >= 0), It.IsAny<CancellationToken>()), Times.Once);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -52,7 +52,7 @@ namespace WireMock.Net.Tests.Owin
|
||||
_requestMapperMock = new Mock<IOwinRequestMapper>();
|
||||
_requestMapperMock.SetupAllProperties();
|
||||
var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "GET", "::1");
|
||||
_requestMapperMock.Setup(m => m.MapAsync(It.IsAny<IRequest>())).ReturnsAsync(request);
|
||||
_requestMapperMock.Setup(m => m.MapAsync(It.IsAny<IRequest>(), It.IsAny<IWireMockMiddlewareOptions>())).ReturnsAsync(request);
|
||||
|
||||
_responseMapperMock = new Mock<IOwinResponseMapper>();
|
||||
_responseMapperMock.SetupAllProperties();
|
||||
@@ -87,7 +87,7 @@ namespace WireMock.Net.Tests.Owin
|
||||
{
|
||||
// Assign
|
||||
var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "GET", "::1", null, new Dictionary<string, string[]>());
|
||||
_requestMapperMock.Setup(m => m.MapAsync(It.IsAny<IRequest>())).ReturnsAsync(request);
|
||||
_requestMapperMock.Setup(m => m.MapAsync(It.IsAny<IRequest>(), It.IsAny<IWireMockMiddlewareOptions>())).ReturnsAsync(request);
|
||||
|
||||
_optionsMock.SetupGet(o => o.AuthorizationMatcher).Returns(new ExactMatcher());
|
||||
_mappingMock.SetupGet(m => m.IsAdminInterface).Returns(true);
|
||||
@@ -108,7 +108,7 @@ namespace WireMock.Net.Tests.Owin
|
||||
{
|
||||
// Assign
|
||||
var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "GET", "::1", null, new Dictionary<string, string[]> { { "h", new[] { "x" } } });
|
||||
_requestMapperMock.Setup(m => m.MapAsync(It.IsAny<IRequest>())).ReturnsAsync(request);
|
||||
_requestMapperMock.Setup(m => m.MapAsync(It.IsAny<IRequest>(), It.IsAny<IWireMockMiddlewareOptions>())).ReturnsAsync(request);
|
||||
|
||||
_optionsMock.SetupGet(o => o.AuthorizationMatcher).Returns(new ExactMatcher());
|
||||
_mappingMock.SetupGet(m => m.IsAdminInterface).Returns(true);
|
||||
|
||||
@@ -187,6 +187,28 @@ namespace WireMock.Net.Tests.RequestMatchers
|
||||
objectMatcherMock.Verify(m => m.IsMatch(42), Times.Once);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RequestMessageBodyMatcher_GetMatchingScore_BodyAsJson_CSharpCodeMatcher()
|
||||
{
|
||||
// Assign
|
||||
var body = new BodyData
|
||||
{
|
||||
BodyAsJson = new { value = 42 },
|
||||
DetectedBodyType = BodyType.Json
|
||||
};
|
||||
|
||||
var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1", body);
|
||||
|
||||
var matcher = new RequestMessageBodyMatcher(new CSharpCodeMatcher(MatchBehaviour.AcceptOnMatch, "return it.value == 42;"));
|
||||
|
||||
// Act
|
||||
var result = new RequestMatchResult();
|
||||
double score = matcher.GetMatchingScore(requestMessage, result);
|
||||
|
||||
// Assert
|
||||
Check.That(score).IsEqualTo(1.0d);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RequestMessageBodyMatcher_GetMatchingScore_BodyAsBytes_IObjectMatcher()
|
||||
{
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
using FluentAssertions;
|
||||
using Moq;
|
||||
using System.Threading.Tasks;
|
||||
using WireMock.Models;
|
||||
using WireMock.ResponseBuilders;
|
||||
using WireMock.Settings;
|
||||
using Xunit;
|
||||
|
||||
namespace WireMock.Net.Tests.ResponseBuilders
|
||||
{
|
||||
public class ResponseWithWithFaultTests
|
||||
{
|
||||
private readonly Mock<IFluentMockServerSettings> _settingsMock = new Mock<IFluentMockServerSettings>();
|
||||
private const string ClientIp = "::1";
|
||||
|
||||
[Theory]
|
||||
[InlineData(FaultType.EMPTY_RESPONSE)]
|
||||
[InlineData(FaultType.MALFORMED_RESPONSE_CHUNK)]
|
||||
public async Task Response_ProvideResponse_WithFault(FaultType faultType)
|
||||
{
|
||||
// Arrange
|
||||
var request = new RequestMessage(new UrlDetails("http://localhost/fault"), "GET", ClientIp);
|
||||
|
||||
// Act
|
||||
var response = Response.Create().WithFault(faultType);
|
||||
var responseMessage = await response.ProvideResponseAsync(request, _settingsMock.Object);
|
||||
|
||||
// Assert
|
||||
responseMessage.FaultType.Should().Be(faultType);
|
||||
responseMessage.FaultPercentage.Should().BeNull();
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(FaultType.EMPTY_RESPONSE, 0.5)]
|
||||
public async Task Response_ProvideResponse_WithFault_IncludingPercentage(FaultType faultType, double percentage)
|
||||
{
|
||||
// Arrange
|
||||
var request = new RequestMessage(new UrlDetails("http://localhost/fault"), "GET", ClientIp);
|
||||
|
||||
// Act
|
||||
var response = Response.Create().WithFault(faultType, percentage);
|
||||
var responseMessage = await response.ProvideResponseAsync(request, _settingsMock.Object);
|
||||
|
||||
// Assert
|
||||
responseMessage.FaultType.Should().Be(faultType);
|
||||
responseMessage.FaultPercentage.Should().Be(percentage);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
using NFluent;
|
||||
using FluentAssertions;
|
||||
using NFluent;
|
||||
using WireMock.Logging;
|
||||
using WireMock.Models;
|
||||
using WireMock.ResponseBuilders;
|
||||
using WireMock.Serialization;
|
||||
using WireMock.Util;
|
||||
using Xunit;
|
||||
@@ -59,8 +61,7 @@ namespace WireMock.Net.Tests.Serialization
|
||||
// Assign
|
||||
var logEntry = new LogEntry
|
||||
{
|
||||
RequestMessage = new RequestMessage(new UrlDetails("http://localhost"), "get", "::1"
|
||||
),
|
||||
RequestMessage = new RequestMessage(new UrlDetails("http://localhost"), "get", "::1"),
|
||||
ResponseMessage = new ResponseMessage
|
||||
{
|
||||
BodyData = new BodyData
|
||||
@@ -88,5 +89,32 @@ namespace WireMock.Net.Tests.Serialization
|
||||
Check.That(result.Response.BodyAsJson).IsNull();
|
||||
Check.That(result.Response.BodyAsFile).IsEqualTo("test");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LogEntryMapper_Map_LogEntry_WithFault()
|
||||
{
|
||||
// Assign
|
||||
var logEntry = new LogEntry
|
||||
{
|
||||
RequestMessage = new RequestMessage(new UrlDetails("http://localhost"), "get", "::1"),
|
||||
ResponseMessage = new ResponseMessage
|
||||
{
|
||||
BodyData = new BodyData
|
||||
{
|
||||
DetectedBodyType = BodyType.File,
|
||||
BodyAsFile = "test"
|
||||
},
|
||||
FaultType = FaultType.EMPTY_RESPONSE,
|
||||
FaultPercentage = 0.5
|
||||
}
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = LogEntryMapper.Map(logEntry);
|
||||
|
||||
// Assert
|
||||
result.Response.FaultType.Should().Be("EMPTY_RESPONSE");
|
||||
result.Response.FaultPercentage.Should().Be(0.5);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -52,12 +52,19 @@ namespace WireMock.Net.Tests
|
||||
public static void SetPrivatePropertyValue<T>(this object obj, string propertyName, T value)
|
||||
{
|
||||
Type t = obj.GetType();
|
||||
if (t.GetProperty(propertyName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance) == null)
|
||||
PropertyInfo propertyInfo = null;
|
||||
while (propertyInfo == null && t != null)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(propertyName), $"Property {propertyName} was not found in Type {obj.GetType().FullName}");
|
||||
propertyInfo = t.GetProperty(propertyName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
t = t.BaseType;
|
||||
}
|
||||
|
||||
t.InvokeMember(propertyName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.SetProperty | BindingFlags.Instance, null, obj, new object[] { value });
|
||||
if (propertyInfo == null)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(propertyName), $"Private property {propertyName} was not found in Type {obj.GetType().FullName}");
|
||||
}
|
||||
|
||||
propertyInfo.SetValue(obj, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,168 +1,185 @@
|
||||
using NFluent;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using WireMock.Util;
|
||||
using Xunit;
|
||||
|
||||
namespace WireMock.Net.Tests.Util
|
||||
{
|
||||
public class BodyParserTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData("application/json", "{ \"x\": 1 }", BodyType.Json, BodyType.Json)]
|
||||
[InlineData("application/json; charset=utf-8", "{ \"x\": 1 }", BodyType.Json, BodyType.Json)]
|
||||
[InlineData("application/json; odata.metadata=minimal", "{ \"x\": 1 }", BodyType.Json, BodyType.Json)]
|
||||
[InlineData("application/vnd.api+json", "{ \"x\": 1 }", BodyType.Json, BodyType.Json)]
|
||||
[InlineData("application/vnd.test+json", "{ \"x\": 1 }", BodyType.Json, BodyType.Json)]
|
||||
public async Task BodyParser_Parse_ContentTypeJson(string contentType, string bodyAsJson, BodyType detectedBodyType, BodyType detectedBodyTypeFromContentType)
|
||||
{
|
||||
// Arrange
|
||||
var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(bodyAsJson));
|
||||
|
||||
// Act
|
||||
var body = await BodyParser.Parse(memoryStream, contentType);
|
||||
|
||||
// Assert
|
||||
Check.That(body.BodyAsBytes).IsNotNull();
|
||||
Check.That(body.BodyAsJson).IsNotNull();
|
||||
Check.That(body.BodyAsString).Equals(bodyAsJson);
|
||||
Check.That(body.DetectedBodyType).IsEqualTo(detectedBodyType);
|
||||
Check.That(body.DetectedBodyTypeFromContentType).IsEqualTo(detectedBodyTypeFromContentType);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("application/xml", "<xml>hello</xml>", BodyType.String, BodyType.String)]
|
||||
[InlineData("something", "hello", BodyType.String, BodyType.Bytes)]
|
||||
public async Task BodyParser_Parse_ContentTypeString(string contentType, string bodyAsString, BodyType detectedBodyType, BodyType detectedBodyTypeFromContentType)
|
||||
{
|
||||
// Arrange
|
||||
var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(bodyAsString));
|
||||
|
||||
// Act
|
||||
var body = await BodyParser.Parse(memoryStream, contentType);
|
||||
|
||||
// Assert
|
||||
Check.That(body.BodyAsBytes).IsNotNull();
|
||||
Check.That(body.BodyAsJson).IsNull();
|
||||
Check.That(body.BodyAsString).Equals(bodyAsString);
|
||||
Check.That(body.DetectedBodyType).IsEqualTo(detectedBodyType);
|
||||
Check.That(body.DetectedBodyTypeFromContentType).IsEqualTo(detectedBodyTypeFromContentType);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(new byte[] {34, 97, 34}, BodyType.Json)]
|
||||
[InlineData(new byte[] {97}, BodyType.String)]
|
||||
[InlineData(new byte[] {0xFF, 0xD8, 0xFF, 0xE0}, BodyType.Bytes)]
|
||||
public async Task BodyParser_Parse_DetectedBodyType(byte[] content, BodyType detectedBodyType)
|
||||
{
|
||||
// arrange
|
||||
var memoryStream = new MemoryStream(content);
|
||||
|
||||
// act
|
||||
var body = await BodyParser.Parse(memoryStream, null);
|
||||
|
||||
// assert
|
||||
Check.That(body.DetectedBodyType).IsEqualTo(detectedBodyType);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task BodyParser_Parse_WithUTF8EncodingAndContentTypeMultipart_DetectedBodyTypeEqualsString()
|
||||
{
|
||||
// Arrange
|
||||
string contentType = "multipart/form-data";
|
||||
string body = @"
|
||||
|
||||
-----------------------------9051914041544843365972754266
|
||||
Content-Disposition: form-data; name=""text""
|
||||
|
||||
text default
|
||||
-----------------------------9051914041544843365972754266
|
||||
Content-Disposition: form-data; name=""file1""; filename=""a.txt""
|
||||
Content-Type: text/plain
|
||||
|
||||
Content of a txt
|
||||
|
||||
-----------------------------9051914041544843365972754266
|
||||
Content-Disposition: form-data; name=""file2""; filename=""a.html""
|
||||
Content-Type: text/html
|
||||
|
||||
<!DOCTYPE html><title>Content of a.html.</title>
|
||||
|
||||
-----------------------------9051914041544843365972754266--";
|
||||
|
||||
var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(body));
|
||||
|
||||
// Act
|
||||
var result = await BodyParser.Parse(memoryStream, contentType);
|
||||
|
||||
// Assert
|
||||
Check.That(result.DetectedBodyType).IsEqualTo(BodyType.String);
|
||||
Check.That(result.DetectedBodyTypeFromContentType).IsEqualTo(BodyType.MultiPart);
|
||||
Check.That(result.BodyAsBytes).IsNotNull();
|
||||
Check.That(result.BodyAsJson).IsNull();
|
||||
Check.That(result.BodyAsString).IsNotNull();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task BodyParser_Parse_WithUTF16EncodingAndContentTypeMultipart_DetectedBodyTypeEqualsString()
|
||||
{
|
||||
// Arrange
|
||||
string contentType = "multipart/form-data";
|
||||
string body = char.ConvertFromUtf32(0x1D161); //U+1D161 = MUSICAL SYMBOL SIXTEENTH NOTE
|
||||
|
||||
var memoryStream = new MemoryStream(Encoding.UTF32.GetBytes(body));
|
||||
|
||||
// Act
|
||||
var result = await BodyParser.Parse(memoryStream, contentType);
|
||||
|
||||
// Assert
|
||||
Check.That(result.DetectedBodyType).IsEqualTo(BodyType.Bytes);
|
||||
Check.That(result.DetectedBodyTypeFromContentType).IsEqualTo(BodyType.MultiPart);
|
||||
Check.That(result.BodyAsBytes).IsNotNull();
|
||||
Check.That(result.BodyAsJson).IsNull();
|
||||
Check.That(result.BodyAsString).IsNull();
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(null, "hello", BodyType.String, BodyType.Bytes)]
|
||||
public async Task BodyParser_Parse_ContentTypeIsNull(string contentType, string bodyAsString, BodyType detectedBodyType, BodyType detectedBodyTypeFromContentType)
|
||||
{
|
||||
// Arrange
|
||||
var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(bodyAsString));
|
||||
|
||||
// Act
|
||||
var body = await BodyParser.Parse(memoryStream, contentType);
|
||||
|
||||
// Assert
|
||||
Check.That(body.BodyAsBytes).IsNotNull();
|
||||
Check.That(body.BodyAsJson).IsNull();
|
||||
Check.That(body.BodyAsString).Equals(bodyAsString);
|
||||
Check.That(body.DetectedBodyType).IsEqualTo(detectedBodyType);
|
||||
Check.That(body.DetectedBodyTypeFromContentType).IsEqualTo(detectedBodyTypeFromContentType);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("HEAD", false)]
|
||||
[InlineData("GET", false)]
|
||||
[InlineData("PUT", true)]
|
||||
[InlineData("POST", true)]
|
||||
using NFluent;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using WireMock.Util;
|
||||
using Xunit;
|
||||
|
||||
namespace WireMock.Net.Tests.Util
|
||||
{
|
||||
public class BodyParserTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData("application/json", "{ \"x\": 1 }", BodyType.Json, BodyType.Json)]
|
||||
[InlineData("application/json; charset=utf-8", "{ \"x\": 1 }", BodyType.Json, BodyType.Json)]
|
||||
[InlineData("application/json; odata.metadata=minimal", "{ \"x\": 1 }", BodyType.Json, BodyType.Json)]
|
||||
[InlineData("application/vnd.api+json", "{ \"x\": 1 }", BodyType.Json, BodyType.Json)]
|
||||
[InlineData("application/vnd.test+json", "{ \"x\": 1 }", BodyType.Json, BodyType.Json)]
|
||||
public async Task BodyParser_Parse_ContentTypeJson(string contentType, string bodyAsJson, BodyType detectedBodyType, BodyType detectedBodyTypeFromContentType)
|
||||
{
|
||||
// Arrange
|
||||
var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(bodyAsJson));
|
||||
|
||||
// Act
|
||||
var body = await BodyParser.Parse(memoryStream, contentType);
|
||||
|
||||
// Assert
|
||||
Check.That(body.BodyAsBytes).IsNotNull();
|
||||
Check.That(body.BodyAsJson).IsNotNull();
|
||||
Check.That(body.BodyAsString).Equals(bodyAsJson);
|
||||
Check.That(body.DetectedBodyType).IsEqualTo(detectedBodyType);
|
||||
Check.That(body.DetectedBodyTypeFromContentType).IsEqualTo(detectedBodyTypeFromContentType);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("application/xml", "<xml>hello</xml>", BodyType.String, BodyType.String)]
|
||||
[InlineData("something", "hello", BodyType.String, BodyType.Bytes)]
|
||||
public async Task BodyParser_Parse_ContentTypeString(string contentType, string bodyAsString, BodyType detectedBodyType, BodyType detectedBodyTypeFromContentType)
|
||||
{
|
||||
// Arrange
|
||||
var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(bodyAsString));
|
||||
|
||||
// Act
|
||||
var body = await BodyParser.Parse(memoryStream, contentType);
|
||||
|
||||
// Assert
|
||||
Check.That(body.BodyAsBytes).IsNotNull();
|
||||
Check.That(body.BodyAsJson).IsNull();
|
||||
Check.That(body.BodyAsString).Equals(bodyAsString);
|
||||
Check.That(body.DetectedBodyType).IsEqualTo(detectedBodyType);
|
||||
Check.That(body.DetectedBodyTypeFromContentType).IsEqualTo(detectedBodyTypeFromContentType);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(new byte[] {34, 97, 34}, BodyType.Json)]
|
||||
[InlineData(new byte[] {97}, BodyType.String)]
|
||||
[InlineData(new byte[] {0xFF, 0xD8, 0xFF, 0xE0}, BodyType.Bytes)]
|
||||
public async Task BodyParser_Parse_DetectedBodyType(byte[] content, BodyType detectedBodyType)
|
||||
{
|
||||
// arrange
|
||||
var memoryStream = new MemoryStream(content);
|
||||
|
||||
// act
|
||||
var body = await BodyParser.Parse(memoryStream, null);
|
||||
|
||||
// assert
|
||||
Check.That(body.DetectedBodyType).IsEqualTo(detectedBodyType);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task BodyParser_Parse_WithUTF8EncodingAndContentTypeMultipart_DetectedBodyTypeEqualsString()
|
||||
{
|
||||
// Arrange
|
||||
string contentType = "multipart/form-data";
|
||||
string body = @"
|
||||
|
||||
-----------------------------9051914041544843365972754266
|
||||
Content-Disposition: form-data; name=""text""
|
||||
|
||||
text default
|
||||
-----------------------------9051914041544843365972754266
|
||||
Content-Disposition: form-data; name=""file1""; filename=""a.txt""
|
||||
Content-Type: text/plain
|
||||
|
||||
Content of a txt
|
||||
|
||||
-----------------------------9051914041544843365972754266
|
||||
Content-Disposition: form-data; name=""file2""; filename=""a.html""
|
||||
Content-Type: text/html
|
||||
|
||||
<!DOCTYPE html><title>Content of a.html.</title>
|
||||
|
||||
-----------------------------9051914041544843365972754266--";
|
||||
|
||||
var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(body));
|
||||
|
||||
// Act
|
||||
var result = await BodyParser.Parse(memoryStream, contentType);
|
||||
|
||||
// Assert
|
||||
Check.That(result.DetectedBodyType).IsEqualTo(BodyType.String);
|
||||
Check.That(result.DetectedBodyTypeFromContentType).IsEqualTo(BodyType.MultiPart);
|
||||
Check.That(result.BodyAsBytes).IsNotNull();
|
||||
Check.That(result.BodyAsJson).IsNull();
|
||||
Check.That(result.BodyAsString).IsNotNull();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task BodyParser_Parse_WithUTF16EncodingAndContentTypeMultipart_DetectedBodyTypeEqualsString()
|
||||
{
|
||||
// Arrange
|
||||
string contentType = "multipart/form-data";
|
||||
string body = char.ConvertFromUtf32(0x1D161); //U+1D161 = MUSICAL SYMBOL SIXTEENTH NOTE
|
||||
|
||||
var memoryStream = new MemoryStream(Encoding.UTF32.GetBytes(body));
|
||||
|
||||
// Act
|
||||
var result = await BodyParser.Parse(memoryStream, contentType);
|
||||
|
||||
// Assert
|
||||
Check.That(result.DetectedBodyType).IsEqualTo(BodyType.Bytes);
|
||||
Check.That(result.DetectedBodyTypeFromContentType).IsEqualTo(BodyType.MultiPart);
|
||||
Check.That(result.BodyAsBytes).IsNotNull();
|
||||
Check.That(result.BodyAsJson).IsNull();
|
||||
Check.That(result.BodyAsString).IsNull();
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(null, "hello", BodyType.String, BodyType.Bytes)]
|
||||
public async Task BodyParser_Parse_ContentTypeIsNull(string contentType, string bodyAsString, BodyType detectedBodyType, BodyType detectedBodyTypeFromContentType)
|
||||
{
|
||||
// Arrange
|
||||
var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(bodyAsString));
|
||||
|
||||
// Act
|
||||
var body = await BodyParser.Parse(memoryStream, contentType);
|
||||
|
||||
// Assert
|
||||
Check.That(body.BodyAsBytes).IsNotNull();
|
||||
Check.That(body.BodyAsJson).IsNull();
|
||||
Check.That(body.BodyAsString).Equals(bodyAsString);
|
||||
Check.That(body.DetectedBodyType).IsEqualTo(detectedBodyType);
|
||||
Check.That(body.DetectedBodyTypeFromContentType).IsEqualTo(detectedBodyTypeFromContentType);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("HEAD", false)]
|
||||
[InlineData("GET", false)]
|
||||
[InlineData("PUT", true)]
|
||||
[InlineData("POST", true)]
|
||||
[InlineData("DELETE", false)]
|
||||
[InlineData("TRACE", false)]
|
||||
[InlineData("OPTIONS", true)]
|
||||
[InlineData("CONNECT", false)]
|
||||
[InlineData("PATCH", true)]
|
||||
public void BodyParser_ShouldParseBody_ExpectedResultForKnownMethods(string method, bool resultShouldBe)
|
||||
[InlineData("PATCH", true)]
|
||||
public void BodyParser_ShouldParseBodyForMethodAndAllowAllIsFalse_ExpectedResultForKnownMethods(string method, bool resultShouldBe)
|
||||
{
|
||||
Check.That(BodyParser.ShouldParseBody(method)).Equals(resultShouldBe);
|
||||
Check.That(BodyParser.ShouldParseBody(method, false)).Equals(resultShouldBe);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("REPORT")]
|
||||
[InlineData("SOME-UNKNOWN-METHOD")]
|
||||
[Theory]
|
||||
[InlineData("HEAD")]
|
||||
[InlineData("GET")]
|
||||
[InlineData("PUT")]
|
||||
[InlineData("POST")]
|
||||
[InlineData("DELETE")]
|
||||
[InlineData("TRACE")]
|
||||
[InlineData("OPTIONS")]
|
||||
[InlineData("CONNECT")]
|
||||
[InlineData("PATCH")]
|
||||
[InlineData("REPORT")]
|
||||
[InlineData("SOME-UNKNOWN-METHOD")]
|
||||
public void BodyParser_ShouldParseBodyForMethodAndAllowAllIsTrue_ExpectedResultShouldBeTrue(string method)
|
||||
{
|
||||
Check.That(BodyParser.ShouldParseBody(method, true)).IsTrue();
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("REPORT")]
|
||||
[InlineData("SOME-UNKNOWN-METHOD")]
|
||||
public void BodyParser_ShouldParseBody_DefaultIsTrueForUnknownMethods(string method)
|
||||
{
|
||||
Check.That(BodyParser.ShouldParseBody(method)).IsTrue();
|
||||
}
|
||||
}
|
||||
Check.That(BodyParser.ShouldParseBody(method, false)).IsTrue();
|
||||
}
|
||||
}
|
||||
}
|
||||
75
test/WireMock.Net.Tests/Util/HttpStatusRangeParserTests.cs
Normal file
75
test/WireMock.Net.Tests/Util/HttpStatusRangeParserTests.cs
Normal file
@@ -0,0 +1,75 @@
|
||||
using FluentAssertions;
|
||||
using System;
|
||||
using System.Net;
|
||||
using WireMock.Util;
|
||||
using Xunit;
|
||||
|
||||
namespace WireMock.Net.Tests.Util
|
||||
{
|
||||
/// <summary>
|
||||
/// Based on https://raw.githubusercontent.com/tmenier/Flurl/129565361e135e639f1d44a35a78aea4302ac6ca/Test/Flurl.Test/Http/HttpStatusRangeParserTests.cs
|
||||
/// </summary>
|
||||
public class HttpStatusRangeParserTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData("4**", 399, false)]
|
||||
[InlineData("4**", 400, true)]
|
||||
[InlineData("4**", 499, true)]
|
||||
[InlineData("4**", 500, false)]
|
||||
|
||||
[InlineData("4xx", 399, false)]
|
||||
[InlineData("4xx", 400, true)]
|
||||
[InlineData("4xx", 499, true)]
|
||||
[InlineData("4xx", 500, false)]
|
||||
|
||||
[InlineData("4XX", 399, false)]
|
||||
[InlineData("4XX", 400, true)]
|
||||
[InlineData("4XX", 499, true)]
|
||||
[InlineData("4XX", 500, false)]
|
||||
|
||||
[InlineData("400-499", 399, false)]
|
||||
[InlineData("400-499", 400, true)]
|
||||
[InlineData("400-499", 499, true)]
|
||||
[InlineData("400-499", 500, false)]
|
||||
|
||||
[InlineData("100,3xx,600", 100, true)]
|
||||
[InlineData("100,3xx,600", 101, false)]
|
||||
[InlineData("100,3xx,600", 300, true)]
|
||||
[InlineData("100,3xx,600", 399, true)]
|
||||
[InlineData("100,3xx,600", 400, false)]
|
||||
[InlineData("100,3xx,600", 600, true)]
|
||||
|
||||
[InlineData("400-409,490-499", 399, false)]
|
||||
[InlineData("400-409,490-499", 405, true)]
|
||||
[InlineData("400-409,490-499", 450, false)]
|
||||
[InlineData("400-409,490-499", 495, true)]
|
||||
[InlineData("400-409,490-499", 500, false)]
|
||||
|
||||
[InlineData("*", 0, true)]
|
||||
[InlineData(",,,*", 9999, true)]
|
||||
|
||||
[InlineData("", 0, false)]
|
||||
[InlineData(",,,", 9999, false)]
|
||||
|
||||
[InlineData(null, 399, true)]
|
||||
public void HttpStatusRangeParser_ValidPattern_IsMatch(string pattern, int value, bool expectedResult)
|
||||
{
|
||||
HttpStatusRangeParser.IsMatch(pattern, value).Should().Be(expectedResult);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void HttpStatusRangeParser_ValidPattern_HttpStatusCode_IsMatch()
|
||||
{
|
||||
HttpStatusRangeParser.IsMatch("4xx", HttpStatusCode.BadRequest).Should().BeTrue();
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("-100")]
|
||||
[InlineData("100-")]
|
||||
[InlineData("1yy")]
|
||||
public void HttpStatusRangeParser_InvalidPattern_ThrowsException(string pattern)
|
||||
{
|
||||
Assert.Throws<ArgumentException>(() => HttpStatusRangeParser.IsMatch(pattern, 100));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,10 @@
|
||||
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Remove="Matchers\CSScriptMatcherTests.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\WireMock.Net.StandAlone\WireMock.Net.StandAlone.csproj" />
|
||||
<ProjectReference Include="..\..\src\WireMock.Net\WireMock.Net.csproj" />
|
||||
@@ -37,7 +41,7 @@
|
||||
<PackageReference Include="FluentAssertions" Version="5.7.0" />
|
||||
<PackageReference Include="System.Threading" Version="4.3.0" />
|
||||
<PackageReference Include="RestEase" Version="1.4.7" />
|
||||
<PackageReference Include="RandomDataGenerator.Net" Version="1.0.8" />
|
||||
<PackageReference Include="RandomDataGenerator.Net" Version="1.0.10" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
|
||||
<PackageReference Include="Moq" Version="4.10.1" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
|
||||
|
||||
Reference in New Issue
Block a user