From 1af512fc72e9192ffaf5f44614c8d3922a4d93a3 Mon Sep 17 00:00:00 2001 From: Stef Heyenrath Date: Thu, 25 Oct 2018 14:08:24 +0200 Subject: [PATCH] Update BodyParser logic (#212) * Update BodyParser logic * update logic for byte[] * small update * MyGetKey * myget * dotnet nuget push * dotnet build * Release * . * StringContent * 1.0.4.18-preview-02 * Debug * 1.0.4.18-preview-02 * disable some proxy tests * myget * packagesToPack * fix * true true * Release * 1.0.4.18 * fix * BodyParserTests * ResponseBodyData (#216) * ResponseBodyData * refactor tests * LogEntryMapperTests --- Directory.Build.props | 19 +++ WireMock.Net Solution.sln | 1 + WireMock.Net Solution.sln.DotSettings | 3 + azure-pipelines.yml | 47 +++++- .../Program.cs | 2 +- .../WireMock.Net.StandAlone.csproj | 3 +- .../Admin/Requests/LogRequestModel.cs | 24 ++- .../Admin/Requests/LogResponseModel.cs | 10 ++ .../Http/HttpRequestMessageHelper.cs | 51 +++--- .../Http/HttpResponseMessageHelper.cs | 5 +- src/WireMock.Net/Http/StringContentHelper.cs | 38 +++++ src/WireMock.Net/Mapping.cs | 5 +- src/WireMock.Net/Matchers/IValueMatcher.cs | 2 +- src/WireMock.Net/Matchers/MatchScores.cs | 19 ++- .../Request/RequestMessageBodyMatcher.cs | 36 ++--- .../Owin/Mappers/OwinRequestMapper.cs | 18 +-- .../Owin/Mappers/OwinResponseMapper.cs | 34 ++-- src/WireMock.Net/Owin/OwinSelfHost.cs | 2 +- .../Owin/WireMockMiddlewareOptions.cs | 2 +- src/WireMock.Net/RequestMessage.cs | 47 ++++-- .../ResponseBuilders/IBodyResponseBuilder.cs | 6 +- src/WireMock.Net/ResponseBuilders/Response.cs | 82 ++++++---- src/WireMock.Net/ResponseMessage.cs | 35 +--- src/WireMock.Net/ResponseMessageBuilder.cs | 12 +- .../Serialization/LogEntryMapper.cs | 132 ++++++++++----- .../Serialization/MappingConverter.cs | 42 +++-- .../Server/FluentMockServer.Admin.cs | 30 ++-- src/WireMock.Net/Server/FluentMockServer.cs | 1 - .../Transformers/HandleBarsRegex.cs | 10 +- .../ResponseMessageTransformer.cs | 24 ++- src/WireMock.Net/Util/BodyData.cs | 25 +++ src/WireMock.Net/Util/BodyParser.cs | 150 +++++++++++------- src/WireMock.Net/Util/BodyType.cs | 33 ++++ ...n.cs => ConcurrentObservableCollection.cs} | 14 +- src/WireMock.Net/Util/FileHelper.cs | 6 +- src/WireMock.Net/Util/JsonUtils.cs | 5 +- src/WireMock.Net/Util/UrlUtils.cs | 5 +- src/WireMock.Net/WireMock.Net.csproj | 36 +++-- .../FluentMockServerTests.Admin.cs | 2 +- .../FluentMockServerTests.Proxy.cs | 7 +- .../FluentMockServerTests.Proxy2.cs | 109 +++---------- .../Http/HttpRequestMessageHelperTests.cs | 46 ++++-- test/WireMock.Net.Tests/MatcherMapperTests.cs | 97 ----------- .../Owin/Mappers/OwinResponseMapperTests.cs | 8 +- .../Owin/MappingMatcherTests.cs | 2 +- .../Owin/WireMockMiddlewareTests.cs | 4 +- .../RequestBuilderWithHeaderTests.cs | 2 +- .../RequestBuilderWithUrlTests.cs | 60 +++++++ test/WireMock.Net.Tests/RequestCookieTests.cs | 28 ---- .../RequestMessageBodyMatcherTests.cs | 22 ++- test/WireMock.Net.Tests/RequestTests.cs | 15 +- .../RequestWithBodyTests.cs | 42 +++-- .../WireMock.Net.Tests/RequestWithUrlTests.cs | 56 ------- .../ResponseBuilders/ResponseWithBodyTests.cs | 63 ++++---- .../ResponseWithCallbackTests.cs | 5 +- .../ResponseWithHandlebarsJsonPathTests.cs | 36 +++-- .../ResponseWithHandlebarsLinqTests.cs | 33 ++-- .../ResponseWithHandlebarsRegexTests.cs | 26 +-- .../ResponseWithHandlebarsTests.cs | 35 ++-- .../ResponseWithHeadersTests.cs | 33 ++++ .../ResponseWithProxyTests.cs | 4 +- test/WireMock.Net.Tests/ResponseTests.cs | 29 ---- .../Serialization/LogEntryMapperTests.cs | 92 +++++++++++ .../Serialization/MatcherMapperTests.cs | 62 +++++++- .../Util/BodyParserTests.cs | 68 ++++---- .../WireMock.Net.Tests.csproj | 7 +- 66 files changed, 1186 insertions(+), 823 deletions(-) create mode 100644 Directory.Build.props create mode 100644 src/WireMock.Net/Http/StringContentHelper.cs create mode 100644 src/WireMock.Net/Util/BodyType.cs rename src/WireMock.Net/Util/{ConcurentObservableCollection.cs => ConcurrentObservableCollection.cs} (75%) delete mode 100644 test/WireMock.Net.Tests/MatcherMapperTests.cs create mode 100644 test/WireMock.Net.Tests/RequestBuilders/RequestBuilderWithUrlTests.cs delete mode 100644 test/WireMock.Net.Tests/RequestCookieTests.cs delete mode 100644 test/WireMock.Net.Tests/RequestWithUrlTests.cs delete mode 100644 test/WireMock.Net.Tests/ResponseTests.cs create mode 100644 test/WireMock.Net.Tests/Serialization/LogEntryMapperTests.cs diff --git a/Directory.Build.props b/Directory.Build.props new file mode 100644 index 00000000..6a3dcd7a --- /dev/null +++ b/Directory.Build.props @@ -0,0 +1,19 @@ + + + $(MsBuildAllProjects);$(MsBuildThisFileFullPath) + + + + 1.0.4.18 + + + + + + + + $(Prerelease)-1$(BUILD_BUILDID) + + + + \ No newline at end of file diff --git a/WireMock.Net Solution.sln b/WireMock.Net Solution.sln index 3eb92425..3bccf3d9 100644 --- a/WireMock.Net Solution.sln +++ b/WireMock.Net Solution.sln @@ -13,6 +13,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution azure-pipelines.yml = azure-pipelines.yml build-info.md = build-info.md CHANGELOG.md = CHANGELOG.md + Directory.Build.props = Directory.Build.props GitReleaseNotes.txt = GitReleaseNotes.txt README.md = README.md ReSharper_WireMock.DotSettings = ReSharper_WireMock.DotSettings diff --git a/WireMock.Net Solution.sln.DotSettings b/WireMock.Net Solution.sln.DotSettings index 10779af8..f147855d 100644 --- a/WireMock.Net Solution.sln.DotSettings +++ b/WireMock.Net Solution.sln.DotSettings @@ -8,4 +8,7 @@ WWW XMS XUA + True + True + True \ No newline at end of file diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 07f4e069..29544e3f 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -2,17 +2,20 @@ pool: vmImage: 'vs2017-win2016' variables: - buildConfiguration: 'Debug' + Prerelease: 'ci' buildId: "1$(Build.BuildId)" + buildProjects: '**/src/**/*.csproj' steps: # Print buildId - script: | echo "BuildId = $(buildId)" + displayName: 'Print buildId' # Install SonarScanner - script: | dotnet tool install --global dotnet-sonarscanner + displayName: Install SonarScanner # Begin SonarScanner # See also @@ -22,17 +25,53 @@ steps: # - script: | %USERPROFILE%\.dotnet\tools\dotnet-sonarscanner begin /k:"wiremock" /d:sonar.organization="stefh-github" /d:sonar.host.url="https://sonarcloud.io" /d:sonar.login="$(SONAR_TOKEN)" /v:"$(buildId)" /d:sonar.cs.opencover.reportsPaths="**\coverage.opencover.xml" + displayName: Begin SonarScanner # Build source, tests and run tests for net452 and netcoreapp2.1 (with coverage) - script: | - dotnet test ./test/WireMock.Net.Tests/WireMock.Net.Tests.csproj --configuration $(buildConfiguration) --framework net452 - dotnet test ./test/WireMock.Net.Tests/WireMock.Net.Tests.csproj --configuration $(buildConfiguration) --framework netcoreapp2.1 --logger trx /p:CollectCoverage=true /p:CoverletOutputFormat=opencover + dotnet test ./test/WireMock.Net.Tests/WireMock.Net.Tests.csproj --configuration Debug --framework net452 + dotnet test ./test/WireMock.Net.Tests/WireMock.Net.Tests.csproj --configuration Debug --framework netcoreapp2.1 --logger trx /p:CollectCoverage=true /p:CoverletOutputFormat=opencover + displayName: 'Build source, tests and run tests for net452 and netcoreapp2.1 (with coverage)' # End SonarScanner - script: | %USERPROFILE%\.dotnet\tools\dotnet-sonarscanner end /d:sonar.login="$(SONAR_TOKEN)" + displayName: End SonarScanner - task: PublishTestResults@2 inputs: testRunner: VSTest - testResultsFiles: '**/*.trx' \ No newline at end of file + testResultsFiles: '**/*.trx' + +# 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 MyGet + 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://www.myget.org/F/wiremock-net/api/v3/index.json --no-service-endpoint --api-key $(MyGetKey) \ No newline at end of file diff --git a/examples/WireMock.Net.Console.Proxy.NETCoreApp2/Program.cs b/examples/WireMock.Net.Console.Proxy.NETCoreApp2/Program.cs index 461f66a4..dbbfee78 100644 --- a/examples/WireMock.Net.Console.Proxy.NETCoreApp2/Program.cs +++ b/examples/WireMock.Net.Console.Proxy.NETCoreApp2/Program.cs @@ -24,7 +24,7 @@ namespace WireMock.Net.Console.Proxy.NETCoreApp2 ReadStaticMappings = false, ProxyAndRecordSettings = new ProxyAndRecordSettings { - Url = "https://www.google.com", + Url = "http://postman-echo.com/post", //ClientX509Certificate2ThumbprintOrSubjectName = "www.yourclientcertname.com OR yourcertificatethumbprint (only if the service you're proxying to requires it)", SaveMapping = true, SaveMappingToFile = false, diff --git a/src/WireMock.Net.StandAlone/WireMock.Net.StandAlone.csproj b/src/WireMock.Net.StandAlone/WireMock.Net.StandAlone.csproj index 07228e02..522621ae 100644 --- a/src/WireMock.Net.StandAlone/WireMock.Net.StandAlone.csproj +++ b/src/WireMock.Net.StandAlone/WireMock.Net.StandAlone.csproj @@ -2,7 +2,6 @@ Lightweight StandAlone Http Mocking Server for .Net. WireMock.Net.StandAlone - 1.0.4.18 Stef Heyenrath net451;net452;net46;netstandard1.3;netstandard2.0 true @@ -21,6 +20,8 @@ True True {B6269AAC-170A-43D5-8B9A-579DED3D9A95} + true + true diff --git a/src/WireMock.Net/Admin/Requests/LogRequestModel.cs b/src/WireMock.Net/Admin/Requests/LogRequestModel.cs index fa9bdcb7..0a926377 100644 --- a/src/WireMock.Net/Admin/Requests/LogRequestModel.cs +++ b/src/WireMock.Net/Admin/Requests/LogRequestModel.cs @@ -36,7 +36,7 @@ namespace WireMock.Admin.Requests public string Url { get; set; } /// - /// The absolete URL. + /// The absolute URL. /// public string AbsoluteUrl { get; set; } @@ -56,7 +56,7 @@ namespace WireMock.Admin.Requests public IDictionary> Headers { get; set; } /// - /// Tthe Cookies. + /// The Cookies. /// public IDictionary Cookies { get; set; } @@ -79,5 +79,25 @@ namespace WireMock.Admin.Requests /// The body encoding. /// public EncodingModel BodyEncoding { get; set; } + + /// + /// The DetectedBodyType, valid values are: + /// + /// - None + /// - String + /// - Json + /// - Bytes + /// + public string DetectedBodyType { get; set; } + + /// + /// The DetectedBodyTypeFromContentType, valid values are: + /// + /// - None + /// - String + /// - Json + /// - Bytes + /// + public string DetectedBodyTypeFromContentType { get; set; } } } \ No newline at end of file diff --git a/src/WireMock.Net/Admin/Requests/LogResponseModel.cs b/src/WireMock.Net/Admin/Requests/LogResponseModel.cs index 60190c63..b7b51a76 100644 --- a/src/WireMock.Net/Admin/Requests/LogResponseModel.cs +++ b/src/WireMock.Net/Admin/Requests/LogResponseModel.cs @@ -58,5 +58,15 @@ namespace WireMock.Admin.Requests /// Gets or sets the body. /// public EncodingModel BodyEncoding { get; set; } + + /// + /// The detected body type (detection based on body content). + /// + public BodyType DetectedBodyType { get; set; } + + /// + /// The detected body type (detection based on Content-Type). + /// + public BodyType DetectedBodyTypeFromContentType { get; set; } } } \ No newline at end of file diff --git a/src/WireMock.Net/Http/HttpRequestMessageHelper.cs b/src/WireMock.Net/Http/HttpRequestMessageHelper.cs index c4da3b93..7f892b00 100644 --- a/src/WireMock.Net/Http/HttpRequestMessageHelper.cs +++ b/src/WireMock.Net/Http/HttpRequestMessageHelper.cs @@ -2,16 +2,21 @@ using System.Collections.Generic; using System.Linq; using System.Net.Http; -using System.Text; +using JetBrains.Annotations; using MimeKit; using Newtonsoft.Json; +using WireMock.Util; +using WireMock.Validation; namespace WireMock.Http { internal static class HttpRequestMessageHelper { - public static HttpRequestMessage Create(RequestMessage requestMessage, string url) + internal static HttpRequestMessage Create([NotNull] RequestMessage requestMessage, [NotNull] string url) { + Check.NotNull(requestMessage, nameof(requestMessage)); + Check.NotNullOrEmpty(url, nameof(url)); + var httpRequestMessage = new HttpRequestMessage(new HttpMethod(requestMessage.Method), url); ContentType contentType = null; @@ -21,40 +26,25 @@ namespace WireMock.Http ContentType.TryParse(value, out contentType); } - // Set Body if present - if (requestMessage.BodyAsBytes != null) + switch (requestMessage.BodyData?.DetectedBodyType) { - httpRequestMessage.Content = new ByteArrayContent(requestMessage.BodyAsBytes); - } - else if (requestMessage.BodyAsJson != null) - { - if (contentType != null) - { - var encoding = requestMessage.BodyEncoding ?? Encoding.GetEncoding(contentType.Charset ?? "UTF-8"); - httpRequestMessage.Content = new StringContent(JsonConvert.SerializeObject(requestMessage.BodyAsJson), encoding, contentType.MimeType); - } - else - { - httpRequestMessage.Content = new StringContent(JsonConvert.SerializeObject(requestMessage.BodyAsJson), requestMessage.BodyEncoding); - } - } - else if (requestMessage.Body != null) - { - if (contentType != null) - { - var encoding = requestMessage.BodyEncoding ?? Encoding.GetEncoding(contentType.Charset ?? "UTF-8"); - httpRequestMessage.Content = new StringContent(requestMessage.Body, encoding, contentType.MimeType); - } - else - { - httpRequestMessage.Content = new StringContent(requestMessage.Body, requestMessage.BodyEncoding); - } + case BodyType.Bytes: + httpRequestMessage.Content = new ByteArrayContent(requestMessage.BodyData.BodyAsBytes); + break; + + case BodyType.Json: + httpRequestMessage.Content = StringContentHelper.Create(JsonConvert.SerializeObject(requestMessage.BodyData.BodyAsJson), contentType); + break; + + case BodyType.String: + httpRequestMessage.Content = StringContentHelper.Create(requestMessage.BodyData.BodyAsString, contentType); + break; } // Overwrite the host header httpRequestMessage.Headers.Host = new Uri(url).Authority; - // Set other headers if present and if not excluded + // Set other headers if present if (requestMessage.Headers == null || requestMessage.Headers.Count == 0) { return httpRequestMessage; @@ -63,6 +53,7 @@ namespace WireMock.Http var excludeHeaders = new List { HttpKnownHeaderNames.Host, HttpKnownHeaderNames.ContentLength }; if (contentType != null) { + // Content-Type should be set on the content excludeHeaders.Add(HttpKnownHeaderNames.ContentType); } diff --git a/src/WireMock.Net/Http/HttpResponseMessageHelper.cs b/src/WireMock.Net/Http/HttpResponseMessageHelper.cs index 1be9dfd5..fa134e17 100644 --- a/src/WireMock.Net/Http/HttpResponseMessageHelper.cs +++ b/src/WireMock.Net/Http/HttpResponseMessageHelper.cs @@ -24,10 +24,7 @@ namespace WireMock.Http contentTypeHeader = headers.First(header => string.Equals(header.Key, HttpKnownHeaderNames.ContentType, StringComparison.OrdinalIgnoreCase)).Value; } - var body = await BodyParser.Parse(stream, contentTypeHeader?.FirstOrDefault()); - responseMessage.Body = body.BodyAsString; - responseMessage.BodyAsJson = body.BodyAsJson; - responseMessage.BodyAsBytes = body.BodyAsBytes; + responseMessage.BodyData = await BodyParser.Parse(stream, contentTypeHeader?.FirstOrDefault()); } foreach (var header in headers) diff --git a/src/WireMock.Net/Http/StringContentHelper.cs b/src/WireMock.Net/Http/StringContentHelper.cs new file mode 100644 index 00000000..2d9446f8 --- /dev/null +++ b/src/WireMock.Net/Http/StringContentHelper.cs @@ -0,0 +1,38 @@ +using System.Net.Http; +using System.Net.Http.Headers; +using System.Text; +using JetBrains.Annotations; +using MimeKit; +using WireMock.Validation; + +namespace WireMock.Http +{ + internal static class StringContentHelper + { + /// + /// Creates a StringContent object. Note that the Encoding is only set when it's also set on the original header. + /// + /// The string content (cannot be null) + /// The ContentType (can be null) + /// StringContent + internal static StringContent Create([NotNull] string content, [CanBeNull] ContentType contentType) + { + Check.NotNull(content, nameof(content)); + + if (contentType == null) + { + return new StringContent(content); + } + + if (contentType.Charset == null) + { + var stringContent = new StringContent(content); + stringContent.Headers.ContentType = new MediaTypeHeaderValue(contentType.MimeType); + return stringContent; + } + + var encoding = Encoding.GetEncoding(contentType.Charset); + return new StringContent(content, encoding, contentType.MimeType); + } + } +} \ No newline at end of file diff --git a/src/WireMock.Net/Mapping.cs b/src/WireMock.Net/Mapping.cs index b35a47c3..cbf24ec5 100644 --- a/src/WireMock.Net/Mapping.cs +++ b/src/WireMock.Net/Mapping.cs @@ -24,15 +24,12 @@ namespace WireMock public int Priority { get; } /// - [CanBeNull] public string Scenario { get; } /// - [CanBeNull] public string ExecutionConditionState { get; } /// - [CanBeNull] public string NextState { get; } /// @@ -79,7 +76,7 @@ namespace WireMock } /// - public RequestMatchResult GetRequestMatchResult(RequestMessage requestMessage, [CanBeNull] string nextState) + public RequestMatchResult GetRequestMatchResult(RequestMessage requestMessage, string nextState) { var result = new RequestMatchResult(); diff --git a/src/WireMock.Net/Matchers/IValueMatcher.cs b/src/WireMock.Net/Matchers/IValueMatcher.cs index 36426f4f..503068a7 100644 --- a/src/WireMock.Net/Matchers/IValueMatcher.cs +++ b/src/WireMock.Net/Matchers/IValueMatcher.cs @@ -7,7 +7,7 @@ public interface IValueMatcher: IObjectMatcher { /// - /// Gets the value (can be a string or an obejct). + /// Gets the value (can be a string or an object). /// /// Value object Value { get; } diff --git a/src/WireMock.Net/Matchers/MatchScores.cs b/src/WireMock.Net/Matchers/MatchScores.cs index c4679578..fd03d2d3 100644 --- a/src/WireMock.Net/Matchers/MatchScores.cs +++ b/src/WireMock.Net/Matchers/MatchScores.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Linq; namespace WireMock.Matchers @@ -11,7 +12,7 @@ namespace WireMock.Matchers /// /// The tolerance /// - public const double Tolerance = 0.0001; + public const double Tolerance = 0.000001; /// /// The default mismatch score @@ -28,6 +29,16 @@ namespace WireMock.Matchers /// public const double AlmostPerfect = 0.99; + /// + /// Is the value a perfect match? + /// + /// The value. + /// true/false + public static bool IsPerfect(double value) + { + return Math.Abs(value - Perfect) < Tolerance; + } + /// /// Convert a bool to the score. /// @@ -39,7 +50,7 @@ namespace WireMock.Matchers } /// - /// Calculates the score from multiple funcs. + /// Calculates the score from multiple values. /// /// The values. /// average score @@ -49,7 +60,7 @@ namespace WireMock.Matchers } /// - /// Calculates the score from multiple funcs. + /// Calculates the score from multiple values. /// /// The values. /// average score diff --git a/src/WireMock.Net/Matchers/Request/RequestMessageBodyMatcher.cs b/src/WireMock.Net/Matchers/Request/RequestMessageBodyMatcher.cs index e0a08f1f..18a81443 100644 --- a/src/WireMock.Net/Matchers/Request/RequestMessageBodyMatcher.cs +++ b/src/WireMock.Net/Matchers/Request/RequestMessageBodyMatcher.cs @@ -1,5 +1,6 @@ using System; using JetBrains.Annotations; +using WireMock.Util; using WireMock.Validation; namespace WireMock.Matchers.Request @@ -93,6 +94,7 @@ namespace WireMock.Matchers.Request public RequestMessageBodyMatcher([NotNull] IMatcher matcher) { Check.NotNull(matcher, nameof(matcher)); + Matcher = matcher; } @@ -109,47 +111,41 @@ namespace WireMock.Matchers.Request if (Matcher is IObjectMatcher objectMatcher) { // If the body is a JSON object, try to match. - if (requestMessage.BodyAsJson != null) + if (requestMessage?.BodyData?.DetectedBodyType == BodyType.Json) { - return objectMatcher.IsMatch(requestMessage.BodyAsJson); + return objectMatcher.IsMatch(requestMessage.BodyData.BodyAsJson); } // If the body is a byte array, try to match. - if (requestMessage.BodyAsBytes != null) + if (requestMessage?.BodyData?.DetectedBodyType == BodyType.Bytes) { - return objectMatcher.IsMatch(requestMessage.BodyAsBytes); + return objectMatcher.IsMatch(requestMessage.BodyData.BodyAsBytes); } } // Check if the matcher is a IStringMatcher if (Matcher is IStringMatcher stringMatcher) { - // If the body is a JSON object, try to use Body (string) to match. - if (requestMessage.BodyAsJson != null && requestMessage.Body != null) + // If the body is a Json or a String, use the BodyAsString to match on. + if (requestMessage?.BodyData?.DetectedBodyType == BodyType.Json || requestMessage?.BodyData?.DetectedBodyType == BodyType.String) { - return stringMatcher.IsMatch(requestMessage.Body); - } - - // If the string body is defined, try to match. - if (requestMessage.Body != null) - { - return stringMatcher.IsMatch(requestMessage.Body); + return stringMatcher.IsMatch(requestMessage.BodyData.BodyAsString); } } if (Func != null) { - return MatchScores.ToScore(requestMessage.Body != null && Func(requestMessage.Body)); - } - - if (DataFunc != null) - { - return MatchScores.ToScore(requestMessage.BodyAsBytes != null && DataFunc(requestMessage.BodyAsBytes)); + return MatchScores.ToScore(requestMessage?.BodyData?.DetectedBodyType == BodyType.String && Func(requestMessage.BodyData.BodyAsString)); } if (JsonFunc != null) { - return MatchScores.ToScore(requestMessage.BodyAsJson != null && JsonFunc(requestMessage.BodyAsJson)); + return MatchScores.ToScore(requestMessage?.BodyData?.DetectedBodyType == BodyType.Json && JsonFunc(requestMessage.BodyData.BodyAsJson)); + } + + if (DataFunc != null) + { + return MatchScores.ToScore(requestMessage?.BodyData?.DetectedBodyType == BodyType.Bytes && DataFunc(requestMessage.BodyData.BodyAsBytes)); } return MatchScores.Mismatch; diff --git a/src/WireMock.Net/Owin/Mappers/OwinRequestMapper.cs b/src/WireMock.Net/Owin/Mappers/OwinRequestMapper.cs index b76ce625..6c0e1342 100644 --- a/src/WireMock.Net/Owin/Mappers/OwinRequestMapper.cs +++ b/src/WireMock.Net/Owin/Mappers/OwinRequestMapper.cs @@ -47,7 +47,7 @@ namespace WireMock.Owin.Mappers } BodyData body = null; - if (request.Body != null && ShouldParseBody(method)) + if (request.Body != null && BodyParser.ShouldParseBody(method)) { body = await BodyParser.Parse(request.Body, request.ContentType); } @@ -69,21 +69,5 @@ namespace WireMock.Owin.Mappers #endif return (urldetails, clientIP); } - - private bool ShouldParseBody(string method) - { - /* - HEAD - No defined body semantics. - GET - No defined body semantics. - PUT - Body supported. - POST - Body supported. - DELETE - No defined body semantics. - TRACE - Body not supported. - OPTIONS - Body supported but no semantics on usage (maybe in the future). - CONNECT - No defined body semantics - PATCH - Body supported. - */ - return new[] { "PUT", "POST", "OPTIONS", "PATCH" }.Contains(method.ToUpper()); - } } } \ No newline at end of file diff --git a/src/WireMock.Net/Owin/Mappers/OwinResponseMapper.cs b/src/WireMock.Net/Owin/Mappers/OwinResponseMapper.cs index fc1e1e8a..aefdcafa 100644 --- a/src/WireMock.Net/Owin/Mappers/OwinResponseMapper.cs +++ b/src/WireMock.Net/Owin/Mappers/OwinResponseMapper.cs @@ -45,23 +45,25 @@ namespace WireMock.Owin.Mappers response.StatusCode = responseMessage.StatusCode; byte[] bytes = null; - if (responseMessage.BodyAsBytes != null) + switch (responseMessage.BodyData?.DetectedBodyType) { - bytes = responseMessage.BodyAsBytes; - } - else if (responseMessage.BodyAsFile != null) - { - bytes = File.ReadAllBytes(responseMessage.BodyAsFile); - } - else if (responseMessage.BodyAsJson != null) - { - Formatting formatting = responseMessage.BodyAsJsonIndented == true ? Formatting.Indented : Formatting.None; - string jsonBody = JsonConvert.SerializeObject(responseMessage.BodyAsJson, new JsonSerializerSettings { Formatting = formatting, NullValueHandling = NullValueHandling.Ignore }); - bytes = (responseMessage.BodyEncoding ?? _utf8NoBom).GetBytes(jsonBody); - } - else if (responseMessage.Body != null) - { - bytes = (responseMessage.BodyEncoding ?? _utf8NoBom).GetBytes(responseMessage.Body); + case BodyType.String: + bytes = (responseMessage.BodyData.Encoding ?? _utf8NoBom).GetBytes(responseMessage.BodyData.BodyAsString); + break; + + case BodyType.Json: + 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; + + case BodyType.Bytes: + bytes = responseMessage.BodyData.BodyAsBytes; + break; + + case BodyType.File: + bytes = File.ReadAllBytes(responseMessage.BodyData.BodyAsFile); + break; } SetResponseHeaders(responseMessage, response); diff --git a/src/WireMock.Net/Owin/OwinSelfHost.cs b/src/WireMock.Net/Owin/OwinSelfHost.cs index f6c3c027..eb4e0d14 100644 --- a/src/WireMock.Net/Owin/OwinSelfHost.cs +++ b/src/WireMock.Net/Owin/OwinSelfHost.cs @@ -94,7 +94,7 @@ namespace WireMock.Owin IsStarted = true; // WaitHandle is signaled when the token is cancelled, - // which will be more efficent than Thread.Sleep in while loop + // which will be more efficient than Thread.Sleep in while loop _cts.Token.WaitHandle.WaitOne(); } catch (Exception e) diff --git a/src/WireMock.Net/Owin/WireMockMiddlewareOptions.cs b/src/WireMock.Net/Owin/WireMockMiddlewareOptions.cs index aa7a2f89..cc8741cf 100644 --- a/src/WireMock.Net/Owin/WireMockMiddlewareOptions.cs +++ b/src/WireMock.Net/Owin/WireMockMiddlewareOptions.cs @@ -26,7 +26,7 @@ namespace WireMock.Owin public ConcurrentDictionary Scenarios { get; } = new ConcurrentDictionary(); - public ObservableCollection LogEntries { get; } = new ConcurentObservableCollection(); + public ObservableCollection LogEntries { get; } = new ConcurrentObservableCollection(); public int? RequestLogExpirationDuration { get; set; } diff --git a/src/WireMock.Net/RequestMessage.cs b/src/WireMock.Net/RequestMessage.cs index 8b36290d..5a7262fe 100644 --- a/src/WireMock.Net/RequestMessage.cs +++ b/src/WireMock.Net/RequestMessage.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; using System.Net; using JetBrains.Annotations; using WireMock.Models; @@ -81,19 +80,34 @@ namespace WireMock public string RawQuery { get; } /// - /// The original body as string, this is defined when Body or BodyAsJson are not null. + /// The body. + /// + public BodyData BodyData { get; } + + /// + /// The original body as string. Convenience getter for Handlebars. /// public string Body { get; } /// - /// The body (as JSON object). + /// The body (as JSON object). Convenience getter for Handlebars. /// - public object BodyAsJson { get; set; } + public object BodyAsJson { get; } /// - /// The body (as bytearray). + /// The body (as bytearray). Convenience getter for Handlebars. /// - public byte[] BodyAsBytes { get; set; } + public byte[] BodyAsBytes { get; } + + /// + /// The detected body type. Convenience getter for Handlebars. + /// + public string DetectedBodyType { get; } + + /// + /// The detected body type from the Content-Type header. Convenience getter for Handlebars. + /// + public string DetectedBodyTypeFromContentType { get; } /// /// Gets the Host @@ -115,21 +129,16 @@ namespace WireMock /// public string Origin { get; } - /// - /// The body encoding. - /// - public Encoding BodyEncoding { get; } - /// /// Initializes a new instance of the class. /// /// The original url details. /// The HTTP method. /// The client IP Address. - /// The body. + /// The BodyData. /// The headers. /// The cookies. - public RequestMessage([NotNull] UrlDetails urlDetails, [NotNull] string method, [NotNull] string clientIP, [CanBeNull] BodyData body = null, [CanBeNull] IDictionary headers = null, [CanBeNull] IDictionary cookies = null) + public RequestMessage([NotNull] UrlDetails urlDetails, [NotNull] string method, [NotNull] string clientIP, [CanBeNull] BodyData bodyData = null, [CanBeNull] IDictionary headers = null, [CanBeNull] IDictionary cookies = null) { Check.NotNull(urlDetails, nameof(urlDetails)); Check.NotNull(method, nameof(method)); @@ -150,10 +159,14 @@ namespace WireMock Method = method; ClientIP = clientIP; - Body = body?.BodyAsString; - BodyEncoding = body?.Encoding; - BodyAsJson = body?.BodyAsJson; - BodyAsBytes = body?.BodyAsBytes; + BodyData = bodyData; + + // Convenience getters for e.g. Handlebars + Body = BodyData?.BodyAsString; + BodyAsJson = BodyData?.BodyAsJson; + BodyAsBytes = BodyData?.BodyAsBytes; + DetectedBodyType = BodyData?.DetectedBodyType.ToString(); + DetectedBodyTypeFromContentType = BodyData?.DetectedBodyTypeFromContentType.ToString(); Headers = headers?.ToDictionary(header => header.Key, header => new WireMockList(header.Value)); Cookies = cookies; diff --git a/src/WireMock.Net/ResponseBuilders/IBodyResponseBuilder.cs b/src/WireMock.Net/ResponseBuilders/IBodyResponseBuilder.cs index 2ab12e77..0ebd1c25 100644 --- a/src/WireMock.Net/ResponseBuilders/IBodyResponseBuilder.cs +++ b/src/WireMock.Net/ResponseBuilders/IBodyResponseBuilder.cs @@ -56,17 +56,17 @@ namespace WireMock.ResponseBuilders /// /// WithBody : Create a string response based on a Base64 string (which will be decoded to a normal string). /// - /// The body. + /// The body. /// The Encoding. /// A . [Obsolete("Should not be used, will be removed in future.")] - IResponseBuilder WithBodyFromBase64([NotNull] string bodyAsbase64, [CanBeNull] Encoding encoding = null); + IResponseBuilder WithBodyFromBase64([NotNull] string bodyAsBase64, [CanBeNull] Encoding encoding = null); /// /// WithBodyFromFile : Create a ... response based on a File. /// /// The filename. - /// Defines if this file is cached in memory or retrieved from disk everytime the response is created. + /// Defines if this file is cached in memory or retrieved from disk every time the response is created. /// A . IResponseBuilder WithBodyFromFile([NotNull] string filename, bool cache = true); } diff --git a/src/WireMock.Net/ResponseBuilders/Response.cs b/src/WireMock.Net/ResponseBuilders/Response.cs index 58980af6..fd8da1db 100644 --- a/src/WireMock.Net/ResponseBuilders/Response.cs +++ b/src/WireMock.Net/ResponseBuilders/Response.cs @@ -178,9 +178,12 @@ namespace WireMock.ResponseBuilders return WithCallbackInternal(false, req => new ResponseMessage { - Body = bodyFactory(req), - BodyDestination = destination, - BodyEncoding = encoding ?? Encoding.UTF8 + BodyData = new BodyData + { + DetectedBodyType = BodyType.String, + BodyAsString = bodyFactory(req), + Encoding = encoding ?? Encoding.UTF8 + } }); } @@ -190,19 +193,20 @@ namespace WireMock.ResponseBuilders Check.NotNull(body, nameof(body)); ResponseMessage.BodyDestination = destination; + ResponseMessage.BodyData = new BodyData(); switch (destination) { case BodyDestinationFormat.String: var enc = encoding ?? Encoding.UTF8; - ResponseMessage.BodyAsBytes = null; - ResponseMessage.Body = enc.GetString(body); - ResponseMessage.BodyEncoding = enc; + ResponseMessage.BodyData.DetectedBodyType = BodyType.String; + ResponseMessage.BodyData.BodyAsString = enc.GetString(body); + ResponseMessage.BodyData.Encoding = enc; break; default: - ResponseMessage.BodyAsBytes = body; - ResponseMessage.BodyEncoding = null; + ResponseMessage.BodyData.DetectedBodyType = BodyType.Bytes; + ResponseMessage.BodyData.BodyAsBytes = body; break; } @@ -214,20 +218,20 @@ namespace WireMock.ResponseBuilders { Check.NotNull(filename, nameof(filename)); - ResponseMessage.BodyEncoding = null; - ResponseMessage.BodyAsFileIsCached = cache; + ResponseMessage.BodyData = new BodyData + { + BodyAsFileIsCached = cache + }; if (cache) { - ResponseMessage.Body = null; - ResponseMessage.BodyAsBytes = File.ReadAllBytes(filename); - ResponseMessage.BodyAsFile = null; + ResponseMessage.BodyData.DetectedBodyType = BodyType.Bytes; + ResponseMessage.BodyData.BodyAsBytes = File.ReadAllBytes(filename); } else { - ResponseMessage.Body = null; - ResponseMessage.BodyAsBytes = null; - ResponseMessage.BodyAsFile = filename; + ResponseMessage.BodyData.DetectedBodyType = BodyType.File; + ResponseMessage.BodyData.BodyAsFile = filename; } return this; @@ -241,26 +245,27 @@ namespace WireMock.ResponseBuilders encoding = encoding ?? Encoding.UTF8; ResponseMessage.BodyDestination = destination; - ResponseMessage.BodyEncoding = encoding; + + ResponseMessage.BodyData = new BodyData + { + Encoding = encoding + }; switch (destination) { case BodyDestinationFormat.Bytes: - ResponseMessage.Body = null; - ResponseMessage.BodyAsJson = null; - ResponseMessage.BodyAsBytes = encoding.GetBytes(body); + ResponseMessage.BodyData.DetectedBodyType = BodyType.Bytes; + ResponseMessage.BodyData.BodyAsBytes= encoding.GetBytes(body); break; case BodyDestinationFormat.Json: - ResponseMessage.Body = null; - ResponseMessage.BodyAsJson = JsonConvert.DeserializeObject(body); - ResponseMessage.BodyAsBytes = null; + ResponseMessage.BodyData.DetectedBodyType = BodyType.Json; + ResponseMessage.BodyData.BodyAsJson = JsonConvert.DeserializeObject(body); break; default: - ResponseMessage.Body = body; - ResponseMessage.BodyAsJson = null; - ResponseMessage.BodyAsBytes = null; + ResponseMessage.BodyData.DetectedBodyType = BodyType.String; + ResponseMessage.BodyData.BodyAsString = body; break; } @@ -273,10 +278,14 @@ namespace WireMock.ResponseBuilders Check.NotNull(body, nameof(body)); ResponseMessage.BodyDestination = null; - ResponseMessage.BodyAsJson = body; - ResponseMessage.BodyEncoding = encoding; - ResponseMessage.BodyAsJsonIndented = indented; - + ResponseMessage.BodyData = new BodyData + { + Encoding = encoding, + DetectedBodyType = BodyType.Json, + BodyAsJson = body, + BodyAsJsonIndented = indented + }; + return this; } @@ -287,15 +296,18 @@ namespace WireMock.ResponseBuilders } /// - public IResponseBuilder WithBodyFromBase64(string bodyAsbase64, Encoding encoding = null) + public IResponseBuilder WithBodyFromBase64(string bodyAsBase64, Encoding encoding = null) { - Check.NotNull(bodyAsbase64, nameof(bodyAsbase64)); + Check.NotNull(bodyAsBase64, nameof(bodyAsBase64)); encoding = encoding ?? Encoding.UTF8; - ResponseMessage.BodyDestination = null; - ResponseMessage.Body = encoding.GetString(Convert.FromBase64String(bodyAsbase64)); - ResponseMessage.BodyEncoding = encoding; + ResponseMessage.BodyData = new BodyData + { + Encoding = encoding, + DetectedBodyType = BodyType.String, + BodyAsString = encoding.GetString(Convert.FromBase64String(bodyAsBase64)) + }; return this; } diff --git a/src/WireMock.Net/ResponseMessage.cs b/src/WireMock.Net/ResponseMessage.cs index 79551b67..1d5c49c3 100644 --- a/src/WireMock.Net/ResponseMessage.cs +++ b/src/WireMock.Net/ResponseMessage.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using System.Linq; -using System.Text; using WireMock.Util; using WireMock.Validation; @@ -32,39 +31,9 @@ namespace WireMock public string BodyDestination { get; set; } /// - /// Gets or sets the body as a string. + /// The Body. /// - public string Body { get; set; } - - /// - /// Gets or sets the body as a json object. - /// - public object BodyAsJson { get; set; } - - /// - /// Gets or sets a value indicating whether child objects to be indented according to the Newtonsoft.Json.JsonTextWriter.Indentation and Newtonsoft.Json.JsonTextWriter.IndentChar settings. - /// - public bool? BodyAsJsonIndented { get; set; } - - /// - /// Gets or sets the body as bytes. - /// - public byte[] BodyAsBytes { get; set; } - - /// - /// Gets or sets the body as a file. - /// - public string BodyAsFile { get; set; } - - /// - /// Is the body as file cached? - /// - public bool? BodyAsFileIsCached { get; set; } - - /// - /// Gets or sets the body encoding. - /// - public Encoding BodyEncoding { get; set; } = new UTF8Encoding(false); + public BodyData BodyData { get; set; } /// /// Adds the header. diff --git a/src/WireMock.Net/ResponseMessageBuilder.cs b/src/WireMock.Net/ResponseMessageBuilder.cs index cefe5d36..b4903e89 100644 --- a/src/WireMock.Net/ResponseMessageBuilder.cs +++ b/src/WireMock.Net/ResponseMessageBuilder.cs @@ -16,10 +16,18 @@ namespace WireMock var response = new ResponseMessage { StatusCode = statusCode, - Headers = ContentTypeJsonHeaders, - BodyAsJson = message != null ? new StatusModel { Status = message, Guid = guid } : null + Headers = ContentTypeJsonHeaders }; + if (message != null) + { + response.BodyData = new BodyData + { + DetectedBodyType = BodyType.Json, + BodyAsJson = new StatusModel { Status = message, Guid = guid } + }; + } + return response; } } diff --git a/src/WireMock.Net/Serialization/LogEntryMapper.cs b/src/WireMock.Net/Serialization/LogEntryMapper.cs index ee4a539b..0cd9adf2 100644 --- a/src/WireMock.Net/Serialization/LogEntryMapper.cs +++ b/src/WireMock.Net/Serialization/LogEntryMapper.cs @@ -2,6 +2,7 @@ using WireMock.Admin.Mappings; using WireMock.Admin.Requests; using WireMock.Logging; +using WireMock.Util; namespace WireMock.Serialization { @@ -9,51 +10,102 @@ namespace WireMock.Serialization { public static LogEntryModel Map(LogEntry logEntry) { + var logRequestModel = new LogRequestModel + { + DateTime = logEntry.RequestMessage.DateTime, + ClientIP = logEntry.RequestMessage.ClientIP, + Path = logEntry.RequestMessage.Path, + AbsolutePath = logEntry.RequestMessage.AbsolutePath, + Url = logEntry.RequestMessage.Url, + AbsoluteUrl = logEntry.RequestMessage.AbsoluteUrl, + Query = logEntry.RequestMessage.Query, + Method = logEntry.RequestMessage.Method, + Headers = logEntry.RequestMessage.Headers, + Cookies = logEntry.RequestMessage.Cookies + }; + + if (logEntry.RequestMessage.BodyData != null) + { + logRequestModel.DetectedBodyType = logEntry.RequestMessage.BodyData.DetectedBodyType.ToString(); + logRequestModel.DetectedBodyTypeFromContentType = logEntry.RequestMessage.BodyData.DetectedBodyTypeFromContentType.ToString(); + + switch (logEntry.RequestMessage.BodyData.DetectedBodyType) + { + case BodyType.String: + logRequestModel.Body = logEntry.RequestMessage.BodyData.BodyAsString; + break; + + case BodyType.Json: + logRequestModel.Body = logEntry.RequestMessage.BodyData.BodyAsString; // In case of Json, do also save the Body as string (backwards compatible) + logRequestModel.BodyAsJson = logEntry.RequestMessage.BodyData.BodyAsJson; + break; + + case BodyType.Bytes: + logRequestModel.BodyAsBytes = logEntry.RequestMessage.BodyData.BodyAsBytes; + break; + } + + logRequestModel.BodyEncoding = logEntry.RequestMessage.BodyData.Encoding != null + ? new EncodingModel + { + EncodingName = logEntry.RequestMessage.BodyData.Encoding.EncodingName, + CodePage = logEntry.RequestMessage.BodyData.Encoding.CodePage, + WebName = logEntry.RequestMessage.BodyData.Encoding.WebName + } + : null; + } + + var logResponseModel = new LogResponseModel + { + StatusCode = logEntry.ResponseMessage.StatusCode, + Headers = logEntry.ResponseMessage.Headers + }; + + if (logEntry.ResponseMessage.BodyData != null) + { + logResponseModel.BodyOriginal = logEntry.ResponseMessage.BodyOriginal; + logResponseModel.BodyDestination = logEntry.ResponseMessage.BodyDestination; + + logResponseModel.DetectedBodyType = logEntry.ResponseMessage.BodyData.DetectedBodyType; + logResponseModel.DetectedBodyTypeFromContentType = logEntry.ResponseMessage.BodyData.DetectedBodyTypeFromContentType; + + switch (logEntry.ResponseMessage.BodyData.DetectedBodyType) + { + case BodyType.String: + logResponseModel.Body = logEntry.ResponseMessage.BodyData.BodyAsString; + break; + + case BodyType.Json: + logResponseModel.BodyAsJson = logEntry.ResponseMessage.BodyData.BodyAsJson; + break; + + case BodyType.Bytes: + logResponseModel.BodyAsBytes = logEntry.ResponseMessage.BodyData.BodyAsBytes; + break; + + case BodyType.File: + logResponseModel.BodyAsFile = logEntry.ResponseMessage.BodyData.BodyAsFile; + logResponseModel.BodyAsFileIsCached = logEntry.ResponseMessage.BodyData.BodyAsFileIsCached; + break; + } + + logResponseModel.BodyEncoding = logEntry.ResponseMessage.BodyData.Encoding != null + ? new EncodingModel + { + EncodingName = logEntry.ResponseMessage.BodyData.Encoding.EncodingName, + CodePage = logEntry.ResponseMessage.BodyData.Encoding.CodePage, + WebName = logEntry.ResponseMessage.BodyData.Encoding.WebName + } + : null; + } + return new LogEntryModel { Guid = logEntry.Guid, - Request = new LogRequestModel - { - DateTime = logEntry.RequestMessage.DateTime, - ClientIP = logEntry.RequestMessage.ClientIP, - Path = logEntry.RequestMessage.Path, - AbsolutePath = logEntry.RequestMessage.AbsolutePath, - Url = logEntry.RequestMessage.Url, - AbsoluteUrl = logEntry.RequestMessage.AbsoluteUrl, - Query = logEntry.RequestMessage.Query, - Method = logEntry.RequestMessage.Method, - Body = logEntry.RequestMessage.Body, - BodyAsJson = logEntry.RequestMessage.BodyAsJson, - BodyAsBytes = logEntry.RequestMessage.BodyAsBytes, - Headers = logEntry.RequestMessage.Headers, - Cookies = logEntry.RequestMessage.Cookies, - BodyEncoding = logEntry.RequestMessage.BodyEncoding != null ? new EncodingModel - { - EncodingName = logEntry.RequestMessage.BodyEncoding.EncodingName, - CodePage = logEntry.RequestMessage.BodyEncoding.CodePage, - WebName = logEntry.RequestMessage.BodyEncoding.WebName - } : null - }, - Response = new LogResponseModel - { - StatusCode = logEntry.ResponseMessage.StatusCode, - BodyDestination = logEntry.ResponseMessage.BodyDestination, - Body = logEntry.ResponseMessage.Body, - BodyAsJson = logEntry.ResponseMessage.BodyAsJson, - BodyAsBytes = logEntry.ResponseMessage.BodyAsBytes, - BodyOriginal = logEntry.ResponseMessage.BodyOriginal, - BodyAsFile = logEntry.ResponseMessage.BodyAsFile, - BodyAsFileIsCached = logEntry.ResponseMessage.BodyAsFileIsCached, - Headers = logEntry.ResponseMessage.Headers, - BodyEncoding = logEntry.ResponseMessage.BodyEncoding != null ? new EncodingModel - { - EncodingName = logEntry.ResponseMessage.BodyEncoding.EncodingName, - CodePage = logEntry.ResponseMessage.BodyEncoding.CodePage, - WebName = logEntry.ResponseMessage.BodyEncoding.WebName - } : null - }, MappingGuid = logEntry.MappingGuid, MappingTitle = logEntry.MappingTitle, + Request = logRequestModel, + Response = logResponseModel, RequestMatchResult = logEntry.RequestMatchResult != null ? new LogRequestMatchModel { TotalScore = logEntry.RequestMatchResult.TotalScore, diff --git a/src/WireMock.Net/Serialization/MappingConverter.cs b/src/WireMock.Net/Serialization/MappingConverter.cs index a53b66ab..46b5af01 100644 --- a/src/WireMock.Net/Serialization/MappingConverter.cs +++ b/src/WireMock.Net/Serialization/MappingConverter.cs @@ -100,22 +100,40 @@ namespace WireMock.Serialization mappingModel.Response.BodyDestination = response.ResponseMessage.BodyDestination; mappingModel.Response.StatusCode = response.ResponseMessage.StatusCode; mappingModel.Response.Headers = Map(response.ResponseMessage.Headers); - mappingModel.Response.BodyAsJson = response.ResponseMessage.BodyAsJson; - mappingModel.Response.BodyAsJsonIndented = response.ResponseMessage.BodyAsJsonIndented; - mappingModel.Response.Body = response.ResponseMessage.Body; - mappingModel.Response.BodyAsBytes = response.ResponseMessage.BodyAsBytes; - mappingModel.Response.BodyAsFile = response.ResponseMessage.BodyAsFile; - mappingModel.Response.BodyAsFileIsCached = response.ResponseMessage.BodyAsFileIsCached; mappingModel.Response.UseTransformer = response.UseTransformer; - if (response.ResponseMessage.BodyEncoding != null && response.ResponseMessage.BodyEncoding.WebName != "utf-8") + if (response.ResponseMessage.BodyData != null) { - mappingModel.Response.BodyEncoding = new EncodingModel + switch (response.ResponseMessage.BodyData?.DetectedBodyType) { - EncodingName = response.ResponseMessage.BodyEncoding.EncodingName, - CodePage = response.ResponseMessage.BodyEncoding.CodePage, - WebName = response.ResponseMessage.BodyEncoding.WebName - }; + case BodyType.String: + mappingModel.Response.Body = response.ResponseMessage.BodyData.BodyAsString; + break; + + case BodyType.Json: + mappingModel.Response.BodyAsJson = response.ResponseMessage.BodyData.BodyAsJson; + mappingModel.Response.BodyAsJsonIndented = response.ResponseMessage.BodyData.BodyAsJsonIndented; + break; + + case BodyType.Bytes: + mappingModel.Response.BodyAsBytes = response.ResponseMessage.BodyData.BodyAsBytes; + break; + + case BodyType.File: + mappingModel.Response.BodyAsFile = response.ResponseMessage.BodyData.BodyAsFile; + mappingModel.Response.BodyAsFileIsCached = response.ResponseMessage.BodyData.BodyAsFileIsCached; + break; + } + + if (response.ResponseMessage.BodyData.Encoding != null && response.ResponseMessage.BodyData.Encoding.WebName != "utf-8") + { + mappingModel.Response.BodyEncoding = new EncodingModel + { + EncodingName = response.ResponseMessage.BodyData.Encoding.EncodingName, + CodePage = response.ResponseMessage.BodyData.Encoding.CodePage, + WebName = response.ResponseMessage.BodyData.Encoding.WebName + }; + } } } diff --git a/src/WireMock.Net/Server/FluentMockServer.Admin.cs b/src/WireMock.Net/Server/FluentMockServer.Admin.cs index 02fb8ae3..47f45175 100644 --- a/src/WireMock.Net/Server/FluentMockServer.Admin.cs +++ b/src/WireMock.Net/Server/FluentMockServer.Admin.cs @@ -274,13 +274,13 @@ namespace WireMock.Server } }); - if (requestMessage.BodyAsJson != null) + if (requestMessage.BodyData?.DetectedBodyType == BodyType.Json) { - request.WithBody(new JsonMatcher(MatchBehaviour.AcceptOnMatch, requestMessage.BodyAsJson)); + request.WithBody(new JsonMatcher(MatchBehaviour.AcceptOnMatch, requestMessage.BodyData.BodyAsJson)); } - else if (requestMessage.Body != null) + else if (requestMessage.BodyData?.DetectedBodyType == BodyType.String) { - request.WithBody(new ExactMatcher(MatchBehaviour.AcceptOnMatch, requestMessage.Body)); + request.WithBody(new ExactMatcher(MatchBehaviour.AcceptOnMatch, requestMessage.BodyData.BodyAsString)); } var response = Response.Create(responseMessage); @@ -764,9 +764,13 @@ namespace WireMock.Server { return new ResponseMessage { - Body = JsonConvert.SerializeObject(result, keepNullValues ? _settingsIncludeNullValues : _settings), + BodyData = new BodyData + { + DetectedBodyType = BodyType.String, + BodyAsString = JsonConvert.SerializeObject(result, keepNullValues ? _settingsIncludeNullValues : _settings) + }, StatusCode = 200, - Headers = new Dictionary> { { HttpKnownHeaderNames.ContentType, new WireMockList("application/json") } } + Headers = new Dictionary> { { HttpKnownHeaderNames.ContentType, new WireMockList(ContentTypeJson) } } }; } @@ -777,9 +781,17 @@ namespace WireMock.Server private T DeserializeObject(RequestMessage requestMessage) { - return requestMessage.Body != null ? - JsonConvert.DeserializeObject(requestMessage.Body) : - ((JObject)requestMessage.BodyAsJson).ToObject(); + if (requestMessage?.BodyData?.DetectedBodyType == BodyType.String) + { + return JsonConvert.DeserializeObject(requestMessage.BodyData.BodyAsString); + } + + if (requestMessage?.BodyData?.DetectedBodyType == BodyType.Json) + { + return ((JObject)requestMessage.BodyData.BodyAsJson).ToObject(); + } + + return default(T); } } } \ No newline at end of file diff --git a/src/WireMock.Net/Server/FluentMockServer.cs b/src/WireMock.Net/Server/FluentMockServer.cs index c077d0d8..6ef7421a 100644 --- a/src/WireMock.Net/Server/FluentMockServer.cs +++ b/src/WireMock.Net/Server/FluentMockServer.cs @@ -5,7 +5,6 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; -using System.Threading.Tasks; using Newtonsoft.Json; using WireMock.Handlers; using WireMock.Logging; diff --git a/src/WireMock.Net/Transformers/HandleBarsRegex.cs b/src/WireMock.Net/Transformers/HandleBarsRegex.cs index 05f9300d..7a0ca278 100644 --- a/src/WireMock.Net/Transformers/HandleBarsRegex.cs +++ b/src/WireMock.Net/Transformers/HandleBarsRegex.cs @@ -50,14 +50,12 @@ namespace WireMock.Transformers string ParseAsString(object arg) { - if (arg is string) + if (arg is string argAsString) { - return (string) arg; - } - else - { - throw new NotSupportedException($"The value '{arg}' with type '{arg?.GetType()}' cannot be used in Handlebars Regex."); + return argAsString; } + + throw new NotSupportedException($"The value '{arg}' with type '{arg?.GetType()}' cannot be used in Handlebars Regex."); } return (ParseAsString(arguments[0]), ParseAsString(arguments[1]), arguments.Length == 3 ? arguments[2] : null); diff --git a/src/WireMock.Net/Transformers/ResponseMessageTransformer.cs b/src/WireMock.Net/Transformers/ResponseMessageTransformer.cs index 586219dd..2a8842a5 100644 --- a/src/WireMock.Net/Transformers/ResponseMessageTransformer.cs +++ b/src/WireMock.Net/Transformers/ResponseMessageTransformer.cs @@ -17,12 +17,12 @@ namespace WireMock.Transformers public static ResponseMessage Transform(RequestMessage requestMessage, ResponseMessage original) { - bool bodyIsJson = original.BodyAsJson != null; + bool bodyIsJson = original.BodyData.DetectedBodyType == BodyType.Json; var responseMessage = new ResponseMessage { StatusCode = original.StatusCode }; if (!bodyIsJson) { - responseMessage.BodyOriginal = original.Body; + responseMessage.BodyOriginal = original.BodyData.BodyAsString; } var template = new { request = requestMessage }; @@ -57,7 +57,7 @@ namespace WireMock.Transformers private static void TransformBodyAsJson(object template, ResponseMessage original, ResponseMessage responseMessage) { JToken jToken; - switch (original.BodyAsJson) + switch (original.BodyData.BodyAsJson) { case JObject bodyAsJObject: jToken = bodyAsJObject; @@ -68,13 +68,18 @@ namespace WireMock.Transformers break; default: - jToken = JObject.FromObject(original.BodyAsJson); + jToken = JObject.FromObject(original.BodyData.BodyAsJson); break; } WalkNode(jToken, template); - responseMessage.BodyAsJson = jToken; + responseMessage.BodyData = new BodyData + { + DetectedBodyType = original.BodyData.DetectedBodyType, + DetectedBodyTypeFromContentType = original.BodyData.DetectedBodyTypeFromContentType, + BodyAsJson = jToken + }; } private static void WalkNode(JToken node, object template) @@ -127,9 +132,14 @@ namespace WireMock.Transformers private static void TransformBodyAsString(object template, ResponseMessage original, ResponseMessage responseMessage) { - var templateBody = Handlebars.Compile(original.Body); + var templateBody = Handlebars.Compile(original.BodyData.BodyAsString); - responseMessage.Body = templateBody(template); + responseMessage.BodyData = new BodyData + { + DetectedBodyType = original.BodyData.DetectedBodyType, + DetectedBodyTypeFromContentType = original.BodyData.DetectedBodyTypeFromContentType, + BodyAsString = templateBody(template) + }; } } } \ No newline at end of file diff --git a/src/WireMock.Net/Util/BodyData.cs b/src/WireMock.Net/Util/BodyData.cs index 2444b0f1..965dd9b2 100644 --- a/src/WireMock.Net/Util/BodyData.cs +++ b/src/WireMock.Net/Util/BodyData.cs @@ -26,5 +26,30 @@ namespace WireMock.Util /// The body (as bytearray). /// public byte[] BodyAsBytes { get; set; } + + /// + /// Gets or sets a value indicating whether child objects to be indented according to the Newtonsoft.Json.JsonTextWriter.Indentation and Newtonsoft.Json.JsonTextWriter.IndentChar settings. + /// + public bool? BodyAsJsonIndented { get; set; } + + /// + /// Gets or sets the body as a file. + /// + public string BodyAsFile { get; set; } + + /// + /// Is the body as file cached? + /// + public bool? BodyAsFileIsCached { get; set; } + + /// + /// The detected body type (detection based on body content). + /// + public BodyType DetectedBodyType { get; set; } + + /// + /// The detected body type (detection based on Content-Type). + /// + public BodyType DetectedBodyTypeFromContentType { get; set; } } } \ No newline at end of file diff --git a/src/WireMock.Net/Util/BodyParser.cs b/src/WireMock.Net/Util/BodyParser.cs index 58362917..66b80127 100644 --- a/src/WireMock.Net/Util/BodyParser.cs +++ b/src/WireMock.Net/Util/BodyParser.cs @@ -4,36 +4,112 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using JetBrains.Annotations; +using MimeKit; using Newtonsoft.Json; +using WireMock.Matchers; +using WireMock.Validation; namespace WireMock.Util { internal static class BodyParser { - private static readonly string[] JsonContentTypes = - { - "application/json", - "application/vnd.api+json" + private static readonly Encoding DefaultEncoding = Encoding.UTF8; + + /* + HEAD - No defined body semantics. + GET - No defined body semantics. + PUT - Body supported. + POST - Body supported. + DELETE - No defined body semantics. + TRACE - Body not supported. + OPTIONS - Body supported but no semantics on usage (maybe in the future). + CONNECT - No defined body semantics + PATCH - Body supported. + */ + private static readonly string[] AllowedBodyParseMethods = { "PUT", "POST", "OPTIONS", "PATCH" }; + + private static readonly IStringMatcher[] JsonContentTypesMatchers = { + new WildcardMatcher("application/json", true), + new WildcardMatcher("application/vnd.*+json", true) }; - private static readonly string[] TextContentTypes = + private static readonly IStringMatcher[] TextContentTypeMatchers = { - "text/", - "application/javascript", "application/typescript", - "application/xml", "application/xhtml+xml", - "application/x-www-form-urlencoded" + new WildcardMatcher("text/*", true), + new RegexMatcher("^application\\/(java|type)script$", true), + new WildcardMatcher("application/*xml", true), + new WildcardMatcher("application/x-www-form-urlencoded", true) }; - private static async Task> ReadStringAsync(Stream stream) + public static bool ParseBodyAsIsValid([CanBeNull] string parseBodyAs) { - using (var streamReader = new StreamReader(stream)) - { - string content = await streamReader.ReadToEndAsync(); - - return new Tuple(content, streamReader.CurrentEncoding); - } + return Enum.TryParse(parseBodyAs, out BodyType _); } + public static bool ShouldParseBody([CanBeNull] string method) + { + return AllowedBodyParseMethods.Contains(method, StringComparer.OrdinalIgnoreCase); + } + + public static BodyType DetectBodyTypeFromContentType([CanBeNull] string contentTypeValue) + { + if (string.IsNullOrEmpty(contentTypeValue) || !ContentType.TryParse(contentTypeValue, out ContentType contentType)) + { + return BodyType.Bytes; + } + + if (TextContentTypeMatchers.Any(matcher => MatchScores.IsPerfect(matcher.IsMatch(contentType.MimeType)))) + { + return BodyType.String; + } + + if (JsonContentTypesMatchers.Any(matcher => MatchScores.IsPerfect(matcher.IsMatch(contentType.MimeType)))) + { + return BodyType.Json; + } + + return BodyType.Bytes; + } + + public static async Task Parse([NotNull] Stream stream, [CanBeNull] string contentType) + { + Check.NotNull(stream, nameof(stream)); + + var data = new BodyData + { + BodyAsBytes = await ReadBytesAsync(stream), + DetectedBodyType = BodyType.Bytes, + DetectedBodyTypeFromContentType = DetectBodyTypeFromContentType(contentType) + }; + + // Try to get the body as String + try + { + data.BodyAsString = DefaultEncoding.GetString(data.BodyAsBytes); + data.Encoding = DefaultEncoding; + data.DetectedBodyType = BodyType.String; + + // If string is not null or empty, try to get as Json + if (!string.IsNullOrEmpty(data.BodyAsString)) + { + try + { + data.BodyAsJson = JsonConvert.DeserializeObject(data.BodyAsString, new JsonSerializerSettings { Formatting = Formatting.Indented }); + data.DetectedBodyType = BodyType.Json; + } + catch + { + // JsonConvert failed, just ignore. + } + } + } + catch + { + // Reading as string failed, just ignore + } + + return data; + } private static async Task ReadBytesAsync(Stream stream) { using (var memoryStream = new MemoryStream()) @@ -42,47 +118,5 @@ namespace WireMock.Util return memoryStream.ToArray(); } } - - public static async Task Parse([NotNull] Stream stream, [CanBeNull] string contentTypeHeaderValue) - { - var data = new BodyData(); - - if (contentTypeHeaderValue != null && TextContentTypes.Any(text => contentTypeHeaderValue.StartsWith(text, StringComparison.OrdinalIgnoreCase))) - { - try - { - var stringData = await ReadStringAsync(stream); - data.BodyAsString = stringData.Item1; - data.Encoding = stringData.Item2; - } - catch - { - // Reading as string failed, just get the ByteArray. - data.BodyAsBytes = await ReadBytesAsync(stream); - } - } - else if (contentTypeHeaderValue != null && JsonContentTypes.Any(json => contentTypeHeaderValue.StartsWith(json, StringComparison.OrdinalIgnoreCase))) - { - var stringData = await ReadStringAsync(stream); - data.BodyAsString = stringData.Item1; - data.Encoding = stringData.Item2; - - try - { - data.BodyAsJson = JsonConvert.DeserializeObject(stringData.Item1, new JsonSerializerSettings { Formatting = Formatting.Indented }); - } - catch - { - // JsonConvert failed, just set the Body as string. - data.BodyAsString = stringData.Item1; - } - } - else - { - data.BodyAsBytes = await ReadBytesAsync(stream); - } - - return data; - } } } \ No newline at end of file diff --git a/src/WireMock.Net/Util/BodyType.cs b/src/WireMock.Net/Util/BodyType.cs new file mode 100644 index 00000000..9bc53019 --- /dev/null +++ b/src/WireMock.Net/Util/BodyType.cs @@ -0,0 +1,33 @@ +namespace WireMock.Util +{ + /// + /// The BodyType + /// + public enum BodyType + { + /// + /// No body present + /// + None, + + /// + /// Body is a String + /// + String, + + /// + /// Body is a Json object + /// + Json, + + /// + /// Body is a Byte array + /// + Bytes, + + /// + /// Body is a File + /// + File + } +} \ No newline at end of file diff --git a/src/WireMock.Net/Util/ConcurentObservableCollection.cs b/src/WireMock.Net/Util/ConcurrentObservableCollection.cs similarity index 75% rename from src/WireMock.Net/Util/ConcurentObservableCollection.cs rename to src/WireMock.Net/Util/ConcurrentObservableCollection.cs index 60d2c90d..f85381ca 100644 --- a/src/WireMock.Net/Util/ConcurentObservableCollection.cs +++ b/src/WireMock.Net/Util/ConcurrentObservableCollection.cs @@ -8,26 +8,26 @@ namespace WireMock.Util /// /// The type of elements in the collection. /// - public class ConcurentObservableCollection : ObservableCollection + public class ConcurrentObservableCollection : ObservableCollection { private readonly object _lockObject = new object(); /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - public ConcurentObservableCollection() { } + public ConcurrentObservableCollection() { } /// - /// Initializes a new instance of the class that contains elements copied from the specified list. + /// Initializes a new instance of the class that contains elements copied from the specified list. /// /// The list from which the elements are copied. - public ConcurentObservableCollection(List list) : base(list) { } + public ConcurrentObservableCollection(List list) : base(list) { } /// - /// Initializes a new instance of the class that contains elements copied from the specified collection. + /// Initializes a new instance of the class that contains elements copied from the specified collection. /// /// The collection from which the elements are copied. - public ConcurentObservableCollection(IEnumerable collection) : base(collection) { } + public ConcurrentObservableCollection(IEnumerable collection) : base(collection) { } /// protected override void ClearItems() diff --git a/src/WireMock.Net/Util/FileHelper.cs b/src/WireMock.Net/Util/FileHelper.cs index 5af19661..b391f060 100644 --- a/src/WireMock.Net/Util/FileHelper.cs +++ b/src/WireMock.Net/Util/FileHelper.cs @@ -11,16 +11,16 @@ namespace WireMock.Util private const int NumberOfRetries = 3; private const int DelayOnRetry = 500; - public static string ReadAllTextWithRetryAndDelay([NotNull] IFileSystemHandler filehandler, [NotNull] string path) + public static string ReadAllTextWithRetryAndDelay([NotNull] IFileSystemHandler handler, [NotNull] string path) { - Check.NotNull(filehandler, nameof(filehandler)); + Check.NotNull(handler, nameof(handler)); Check.NotNullOrEmpty(path, nameof(path)); for (int i = 1; i <= NumberOfRetries; ++i) { try { - return filehandler.ReadMappingFile(path); + return handler.ReadMappingFile(path); } catch { diff --git a/src/WireMock.Net/Util/JsonUtils.cs b/src/WireMock.Net/Util/JsonUtils.cs index a8a8715f..79ccba9e 100644 --- a/src/WireMock.Net/Util/JsonUtils.cs +++ b/src/WireMock.Net/Util/JsonUtils.cs @@ -92,7 +92,7 @@ namespace WireMock.Util private static void ProcessItem(JToken node, string path, string propertyName, List lines) { - string castText = string.Empty; + string castText; switch (node.Type) { case JTokenType.Boolean: @@ -132,8 +132,7 @@ namespace WireMock.Util break; default: - throw new NotSupportedException( - $"JTokenType '{node.Type}' cannot be converted to a Dynamic Linq cast operator."); + throw new NotSupportedException($"JTokenType '{node.Type}' cannot be converted to a Dynamic Linq cast operator."); } if (!string.IsNullOrEmpty(propertyName)) diff --git a/src/WireMock.Net/Util/UrlUtils.cs b/src/WireMock.Net/Util/UrlUtils.cs index 78b070a8..7ed37d65 100644 --- a/src/WireMock.Net/Util/UrlUtils.cs +++ b/src/WireMock.Net/Util/UrlUtils.cs @@ -1,6 +1,7 @@ using System; using JetBrains.Annotations; using WireMock.Models; +using WireMock.Validation; #if !USE_ASPNETCORE using Microsoft.Owin; #else @@ -13,6 +14,8 @@ namespace WireMock.Util { public static UrlDetails Parse([NotNull] Uri uri, PathString pathBase) { + Check.NotNull(uri, nameof(uri)); + if (!pathBase.HasValue) { return new UrlDetails(uri, uri); @@ -26,7 +29,7 @@ namespace WireMock.Util private static string RemoveFirst(string text, string search) { - int pos = text.IndexOf(search); + int pos = text.IndexOf(search, StringComparison.Ordinal); if (pos < 0) { return text; diff --git a/src/WireMock.Net/WireMock.Net.csproj b/src/WireMock.Net/WireMock.Net.csproj index 46aff3d7..9a5f95c8 100644 --- a/src/WireMock.Net/WireMock.Net.csproj +++ b/src/WireMock.Net/WireMock.Net.csproj @@ -2,7 +2,6 @@ Lightweight Http Mocking Server for .Net, inspired by WireMock from the Java landscape. WireMock.Net - 1.0.4.18 Stef Heyenrath net451;net452;net46;net461;netstandard1.3;netstandard2.0 true @@ -21,6 +20,8 @@ True True {D3804228-91F4-4502-9595-39584E5A01AD} + true + true @@ -47,57 +48,66 @@ - - - - + + + + + + - - - + + + + + + - - + + + - + + - + + - + + \ No newline at end of file diff --git a/test/WireMock.Net.Tests/FluentMockServerTests.Admin.cs b/test/WireMock.Net.Tests/FluentMockServerTests.Admin.cs index 2667ef88..97e164a4 100644 --- a/test/WireMock.Net.Tests/FluentMockServerTests.Admin.cs +++ b/test/WireMock.Net.Tests/FluentMockServerTests.Admin.cs @@ -319,7 +319,7 @@ namespace WireMock.Net.Tests Check.That(server.LogEntries).HasSize(1); var requestLogged = server.LogEntries.First(); Check.That(requestLogged.RequestMessage.Method).IsEqualTo("GET"); - Check.That(requestLogged.RequestMessage.BodyAsBytes).IsNull(); + Check.That(requestLogged.RequestMessage.BodyData).IsNull(); } [Fact] diff --git a/test/WireMock.Net.Tests/FluentMockServerTests.Proxy.cs b/test/WireMock.Net.Tests/FluentMockServerTests.Proxy.cs index d487ef98..cd696900 100644 --- a/test/WireMock.Net.Tests/FluentMockServerTests.Proxy.cs +++ b/test/WireMock.Net.Tests/FluentMockServerTests.Proxy.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Net; using System.Net.Http; using System.Net.Http.Headers; +using System.Text; using System.Threading.Tasks; using WireMock.RequestBuilders; using WireMock.ResponseBuilders; @@ -67,7 +68,7 @@ namespace WireMock.Net.Tests { Method = HttpMethod.Post, RequestUri = new Uri($"{server.Urls[0]}{path}"), - Content = new StringContent("stringContent") + Content = new StringContent("stringContent", Encoding.ASCII) }; requestMessage.Content.Headers.ContentType = new MediaTypeHeaderValue("text/plain"); requestMessage.Content.Headers.Add("bbb", "test"); @@ -75,7 +76,7 @@ namespace WireMock.Net.Tests // then var receivedRequest = serverForProxyForwarding.LogEntries.First().RequestMessage; - Check.That(receivedRequest.Body).IsEqualTo("stringContent"); + Check.That(receivedRequest.BodyData.BodyAsString).IsEqualTo("stringContent"); Check.That(receivedRequest.Headers).ContainsKey("Content-Type"); Check.That(receivedRequest.Headers["Content-Type"].First()).Contains("text/plain"); Check.That(receivedRequest.Headers).ContainsKey("bbb"); @@ -158,7 +159,7 @@ namespace WireMock.Net.Tests // Assert var receivedRequest = serverForProxyForwarding.LogEntries.First().RequestMessage; - Check.That(receivedRequest.Body).IsEqualTo(""); + Check.That(receivedRequest.BodyData.BodyAsString).IsEqualTo(""); Check.That(receivedRequest.Headers).ContainsKey("Content-Type"); Check.That(receivedRequest.Headers["Content-Type"].First()).Contains("text/plain"); } diff --git a/test/WireMock.Net.Tests/FluentMockServerTests.Proxy2.cs b/test/WireMock.Net.Tests/FluentMockServerTests.Proxy2.cs index 2cdc58e0..2066ce97 100644 --- a/test/WireMock.Net.Tests/FluentMockServerTests.Proxy2.cs +++ b/test/WireMock.Net.Tests/FluentMockServerTests.Proxy2.cs @@ -1,115 +1,46 @@ using NFluent; using System; -using System.Diagnostics; using System.Linq; using System.Net; using System.Net.Http; -using System.Text; -using System.Threading; using System.Threading.Tasks; using WireMock.RequestBuilders; using WireMock.ResponseBuilders; using WireMock.Server; -using WireMock.Settings; using Xunit; -using Xunit.Abstractions; namespace WireMock.Net.Tests { - public class FluentMockServerProxy2Tests : IDisposable + public class FluentMockServerProxy2Tests { - private readonly ITestOutputHelper _output; - private readonly CancellationTokenSource _cts; - private Guid _guid; - private string _url; - - public FluentMockServerProxy2Tests(ITestOutputHelper output) - { - _output = output; - - _cts = new CancellationTokenSource(); - } - - //private Task Run() - //{ - - // return Task.Run(() => - // { - // _guid = Guid.NewGuid(); - - // var targetServer = FluentMockServer.Start(); - // targetServer.Given(Request.Create().UsingPost().WithPath($"/{_guid}")) - // .RespondWith(Response.Create().WithStatusCode(201).WithBodyAsJson(new { p = 42 }).WithHeader("Content-Type", "application/json")); - - // _url = targetServer.Urls[0]; - - // //while (!_cts.IsCancellationRequested) - // //{ - // // Thread.Sleep(100); - // //} - // }, _cts.Token); - //} - - private void X() - { - _guid = Guid.NewGuid(); - - var targetServer = FluentMockServer.Start(); - targetServer.Given(Request.Create().UsingPost().WithPath($"/{_guid}")) - .RespondWith(Response.Create().WithStatusCode(201).WithBodyAsJson(new { p = 42 }).WithHeader("Content-Type", "application/json")); - - _url = targetServer.Urls[0]; - - // Thread.Sleep(TimeSpan.FromSeconds(3)); - - _output.WriteLine(targetServer.Urls[0]); - - //while (!_cts.IsCancellationRequested) - //{ - // Thread.Sleep(100); - //} - } - [Fact] - public void FluentMockServer_ProxyAndRecordSettings_ShouldProxyContentTypeHeader() + public async Task FluentMockServer_ProxyAndRecordSettings_ShouldProxy() { // Assign - _output.WriteLine("This is output fr"); - //var t = new Thread(X); - //t.Start(); - X(); - _output.WriteLine("started"); + var server = FluentMockServer.Start(); - Thread.Sleep(TimeSpan.FromSeconds(4)); + server.Given(Request.Create().UsingPost().WithHeader("prx", "1")) + .RespondWith(Response.Create().WithProxy(server.Urls[0])); - _output.WriteLine("sleep 4 done"); - - var server = FluentMockServer.Start( - new FluentMockServerSettings - { - ProxyAndRecordSettings = new ProxyAndRecordSettings - { - Url = _url - } - } - ); - - _output.WriteLine("started 2"); - _output.WriteLine(server.Urls[0]); + server.Given(Request.Create().UsingPost()) + .RespondWith(Response.Create().WithStatusCode(201).WithBodyAsJson(new { p = 42 }).WithHeader("Content-Type", "application/json")); // Act - var response = new HttpClient().PostAsync(new Uri($"{server.Urls[0]}/{_guid}"), new StringContent("{ \"x\": 1 }", Encoding.UTF8, "application/json")).Result; - //string content = response.Content.ReadAsStringAsync().GetAwaiter().GetResult(); + var request = new HttpRequestMessage + { + Method = HttpMethod.Post, + RequestUri = new Uri($"{server.Urls[0]}/TST"), + Content = new StringContent("test") + }; + request.Headers.Add("prx", "1"); - //// Assert - //Check.That(content).IsEqualTo("{\"p\":42}"); - //Check.That(response.StatusCode).IsEqualTo(HttpStatusCode.Created); - //Check.That(response.Content.Headers.GetValues("Content-Type").First()).IsEqualTo("application/json"); - } + // Assert + var response = await new HttpClient().SendAsync(request); + string content = await response.Content.ReadAsStringAsync(); - public void Dispose() - { - _cts.Cancel(); + Check.That(content).IsEqualTo("{\"p\":42}"); + Check.That(response.StatusCode).IsEqualTo(HttpStatusCode.Created); + Check.That(response.Content.Headers.GetValues("Content-Type").First()).IsEqualTo("application/json"); } } } \ No newline at end of file diff --git a/test/WireMock.Net.Tests/Http/HttpRequestMessageHelperTests.cs b/test/WireMock.Net.Tests/Http/HttpRequestMessageHelperTests.cs index 50af98c8..ff28b539 100644 --- a/test/WireMock.Net.Tests/Http/HttpRequestMessageHelperTests.cs +++ b/test/WireMock.Net.Tests/Http/HttpRequestMessageHelperTests.cs @@ -17,11 +17,7 @@ namespace WireMock.Net.Tests.Http { // Assign var headers = new Dictionary { { "x", new[] { "value-1" } } }; - var body = new BodyData - { - BodyAsString = "hello" - }; - var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "PUT", ClientIp, body, headers); + var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "PUT", ClientIp, null, headers); // Act var message = HttpRequestMessageHelper.Create(request, "http://url"); @@ -36,7 +32,8 @@ namespace WireMock.Net.Tests.Http // Assign var body = new BodyData { - BodyAsBytes = Encoding.UTF8.GetBytes("hi") + BodyAsBytes = Encoding.UTF8.GetBytes("hi"), + DetectedBodyType = BodyType.Bytes }; var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "GET", ClientIp, body); @@ -53,7 +50,8 @@ namespace WireMock.Net.Tests.Http // Assign var body = new BodyData { - BodyAsJson = new { x = 42 } + BodyAsJson = new { x = 42 }, + DetectedBodyType = BodyType.Json }; var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "GET", ClientIp, body); @@ -71,7 +69,28 @@ namespace WireMock.Net.Tests.Http var headers = new Dictionary { { "Content-Type", new[] { "application/json" } } }; var body = new BodyData { - BodyAsJson = new { x = 42 } + BodyAsJson = new { x = 42 }, + DetectedBodyType = BodyType.Json + }; + var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "GET", ClientIp, body, headers); + + // Act + var message = HttpRequestMessageHelper.Create(request, "http://url"); + + // Assert + Check.That(await message.Content.ReadAsStringAsync()).Equals("{\"x\":42}"); + Check.That(message.Content.Headers.GetValues("Content-Type")).ContainsExactly("application/json"); + } + + [Fact] + public async void HttpRequestMessageHelper_Create_Json_With_ContentType_ApplicationJson_UTF8() + { + // Assign + var headers = new Dictionary { { "Content-Type", new[] { "application/json; charset=utf-8" } } }; + var body = new BodyData + { + BodyAsJson = new { x = 42 }, + DetectedBodyType = BodyType.Json }; var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "GET", ClientIp, body, headers); @@ -90,7 +109,8 @@ namespace WireMock.Net.Tests.Http var headers = new Dictionary { { "Content-Type", new[] { "application/xml" } } }; var body = new BodyData { - BodyAsString = "hello" + BodyAsString = "hello", + DetectedBodyType = BodyType.String }; var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "PUT", ClientIp, body, headers); @@ -98,7 +118,7 @@ namespace WireMock.Net.Tests.Http var message = HttpRequestMessageHelper.Create(request, "http://url"); // Assert - Check.That(message.Content.Headers.GetValues("Content-Type")).ContainsExactly("application/xml; charset=utf-8"); + Check.That(message.Content.Headers.GetValues("Content-Type")).ContainsExactly("application/xml"); } [Fact] @@ -108,7 +128,8 @@ namespace WireMock.Net.Tests.Http var headers = new Dictionary { { "Content-Type", new[] { "application/xml; charset=UTF-8" } } }; var body = new BodyData { - BodyAsString = "hello" + BodyAsString = "hello", + DetectedBodyType = BodyType.String }; var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "PUT", ClientIp, body, headers); @@ -126,7 +147,8 @@ namespace WireMock.Net.Tests.Http var headers = new Dictionary { { "Content-Type", new[] { "application/xml; charset=Ascii" } } }; var body = new BodyData { - BodyAsString = "hello" + BodyAsString = "hello", + DetectedBodyType = BodyType.String }; var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "PUT", ClientIp, body, headers); diff --git a/test/WireMock.Net.Tests/MatcherMapperTests.cs b/test/WireMock.Net.Tests/MatcherMapperTests.cs deleted file mode 100644 index d18685d3..00000000 --- a/test/WireMock.Net.Tests/MatcherMapperTests.cs +++ /dev/null @@ -1,97 +0,0 @@ -using System; -using NFluent; -using WireMock.Admin.Mappings; -using WireMock.Matchers; -using WireMock.Serialization; -using Xunit; - -namespace WireMock.Net.Tests -{ - public class MatcherMapperTests - { - [Fact] - public void MatcherMapper_Map_MatcherModel_Null() - { - // Act - var result = MatcherMapper.Map((MatcherModel)null); - - // Assert - Check.That(result).IsNull(); - } - - [Fact] - public void MatcherMapper_Map_MatcherModel_Exception() - { - // Assign - var model = new MatcherModel { Name = "test" }; - - // Act and Assert - Check.ThatCode(() => MatcherMapper.Map(model)).Throws(); - } - - [Fact] - public void MatcherMapper_Map_MatcherModel_LinqMatcher_Pattern() - { - // Assign - var model = new MatcherModel - { - Name = "LinqMatcher", - Pattern = "p" - }; - - // Act - var matcher = MatcherMapper.Map(model) as LinqMatcher; - - // Assert - Check.That(matcher).IsNotNull(); - Check.That(matcher.MatchBehaviour).IsEqualTo(MatchBehaviour.AcceptOnMatch); - Check.That(matcher.GetPatterns()).ContainsExactly("p"); - } - - [Fact] - public void MatcherMapper_Map_MatcherModel_LinqMatcher_Patterns() - { - // Assign - var model = new MatcherModel - { - Name = "LinqMatcher", - Patterns = new[] { "p1", "p2" } - }; - - // Act - var matcher = MatcherMapper.Map(model) as LinqMatcher; - - // Assert - Check.That(matcher).IsNotNull(); - Check.That(matcher.MatchBehaviour).IsEqualTo(MatchBehaviour.AcceptOnMatch); - Check.That(matcher.GetPatterns()).Contains(new[] { "p1", "p2" }); - } - - [Fact] - public void MatcherMapper_Map_IMatcher_Null() - { - // Act - var result = MatcherMapper.Map((IMatcher)null); - - // Assert - Check.That(result).IsNull(); - } - - [Fact] - public void MatcherMapper_Map_IMatcher_LinqMatcher_Pattern() - { - // Assign - var matcher = new LinqMatcher(MatchBehaviour.AcceptOnMatch, "p"); - - // Act - var result = MatcherMapper.Map(matcher); - - // Assert - Check.That(result).IsNotNull(); - Check.That(result.Name).IsEqualTo("LinqMatcher"); - Check.That(result.IgnoreCase).IsNull(); - Check.That(result.Pattern).IsEqualTo("p"); - Check.That(result.Patterns).IsNull(); - } - } -} \ No newline at end of file diff --git a/test/WireMock.Net.Tests/Owin/Mappers/OwinResponseMapperTests.cs b/test/WireMock.Net.Tests/Owin/Mappers/OwinResponseMapperTests.cs index 3590ad46..10c1b004 100644 --- a/test/WireMock.Net.Tests/Owin/Mappers/OwinResponseMapperTests.cs +++ b/test/WireMock.Net.Tests/Owin/Mappers/OwinResponseMapperTests.cs @@ -96,7 +96,7 @@ namespace WireMock.Net.Tests.Owin.Mappers var responseMessage = new ResponseMessage { Headers = new Dictionary>(), - Body = body + BodyData = new BodyData { DetectedBodyType = BodyType.String, BodyAsString = body } }; // Act @@ -114,7 +114,7 @@ namespace WireMock.Net.Tests.Owin.Mappers var responseMessage = new ResponseMessage { Headers = new Dictionary>(), - BodyAsBytes = bytes + BodyData = new BodyData { DetectedBodyType = BodyType.Bytes, BodyAsBytes = bytes } }; // Act @@ -128,11 +128,11 @@ namespace WireMock.Net.Tests.Owin.Mappers public async void OwinResponseMapper_MapAsync_BodyAsJson() { // Assign + var json = new { t = "x", i = (string)null }; var responseMessage = new ResponseMessage { Headers = new Dictionary>(), - BodyAsJson = new { t = "x", i = (string)null }, - BodyAsJsonIndented = false + BodyData = new BodyData { DetectedBodyType = BodyType.Json, BodyAsJson = json, BodyAsJsonIndented = false } }; // Act diff --git a/test/WireMock.Net.Tests/Owin/MappingMatcherTests.cs b/test/WireMock.Net.Tests/Owin/MappingMatcherTests.cs index 3eb1d772..d1b04ccf 100644 --- a/test/WireMock.Net.Tests/Owin/MappingMatcherTests.cs +++ b/test/WireMock.Net.Tests/Owin/MappingMatcherTests.cs @@ -21,7 +21,7 @@ namespace WireMock.Net.Tests.Owin _optionsMock = new Mock(); _optionsMock.SetupAllProperties(); _optionsMock.Setup(o => o.Mappings).Returns(new ConcurrentDictionary()); - _optionsMock.Setup(o => o.LogEntries).Returns(new ConcurentObservableCollection()); + _optionsMock.Setup(o => o.LogEntries).Returns(new ConcurrentObservableCollection()); _optionsMock.Setup(o => o.Scenarios).Returns(new ConcurrentDictionary()); _sut = new MappingMatcher(_optionsMock.Object); diff --git a/test/WireMock.Net.Tests/Owin/WireMockMiddlewareTests.cs b/test/WireMock.Net.Tests/Owin/WireMockMiddlewareTests.cs index ccf75d7f..08470fce 100644 --- a/test/WireMock.Net.Tests/Owin/WireMockMiddlewareTests.cs +++ b/test/WireMock.Net.Tests/Owin/WireMockMiddlewareTests.cs @@ -44,7 +44,7 @@ namespace WireMock.Net.Tests.Owin _optionsMock = new Mock(); _optionsMock.SetupAllProperties(); _optionsMock.Setup(o => o.Mappings).Returns(new ConcurrentDictionary()); - _optionsMock.Setup(o => o.LogEntries).Returns(new ConcurentObservableCollection()); + _optionsMock.Setup(o => o.LogEntries).Returns(new ConcurrentObservableCollection()); _optionsMock.Setup(o => o.Scenarios).Returns(new ConcurrentDictionary()); _optionsMock.Setup(o => o.Logger.Warn(It.IsAny(), It.IsAny())); _optionsMock.Setup(o => o.Logger.Error(It.IsAny(), It.IsAny())); @@ -79,7 +79,7 @@ namespace WireMock.Net.Tests.Owin // Assert and Verify _optionsMock.Verify(o => o.Logger.Warn(It.IsAny(), It.IsAny()), Times.Once); - Expression> match = r => r.StatusCode == 404 && ((StatusModel)r.BodyAsJson).Status == "No matching mapping found"; + Expression> match = r => r.StatusCode == 404 && ((StatusModel)r.BodyData.BodyAsJson).Status == "No matching mapping found"; _responseMapperMock.Verify(m => m.MapAsync(It.Is(match), It.IsAny()), Times.Once); } diff --git a/test/WireMock.Net.Tests/RequestBuilders/RequestBuilderWithHeaderTests.cs b/test/WireMock.Net.Tests/RequestBuilders/RequestBuilderWithHeaderTests.cs index e9a1bfa8..04d98364 100644 --- a/test/WireMock.Net.Tests/RequestBuilders/RequestBuilderWithHeaderTests.cs +++ b/test/WireMock.Net.Tests/RequestBuilders/RequestBuilderWithHeaderTests.cs @@ -73,7 +73,7 @@ namespace WireMock.Net.Tests.RequestBuilders public void RequestBuilder_WithHeader_FuncIDictionary() { // Act - var requestBuilder = (Request)Request.Create().WithHeader((IDictionary x) => true); + var requestBuilder = (Request)Request.Create().WithHeader(x => true); // Assert var matchers = requestBuilder.GetPrivateFieldValue>("_requestMatchers"); diff --git a/test/WireMock.Net.Tests/RequestBuilders/RequestBuilderWithUrlTests.cs b/test/WireMock.Net.Tests/RequestBuilders/RequestBuilderWithUrlTests.cs new file mode 100644 index 00000000..ad95157f --- /dev/null +++ b/test/WireMock.Net.Tests/RequestBuilders/RequestBuilderWithUrlTests.cs @@ -0,0 +1,60 @@ +using System.Collections.Generic; +using NFluent; +using WireMock.Matchers; +using WireMock.Matchers.Request; +using WireMock.RequestBuilders; +using Xunit; + +namespace WireMock.Net.Tests.RequestBuilders +{ + public class RequestBuilderWithUrlTests + { + [Fact] + public void RequestBuilder_WithUrl_Strings() + { + // Act + var requestBuilder = (Request)Request.Create().WithUrl("http://a", "http://b"); + + // Assert + var matchers = requestBuilder.GetPrivateFieldValue>("_requestMatchers"); + Check.That(matchers.Count()).IsEqualTo(1); + Check.That(matchers[0]).IsInstanceOfType(typeof(RequestMessageUrlMatcher)); + } + + [Fact] + public void RequestBuilder_WithUrl_MatchBehaviour_Strings() + { + // Act + var requestBuilder = (Request)Request.Create().WithUrl(MatchBehaviour.AcceptOnMatch, "http://a", "http://b"); + + // Assert + var matchers = requestBuilder.GetPrivateFieldValue>("_requestMatchers"); + Check.That(matchers.Count()).IsEqualTo(1); + Check.That(matchers[0]).IsInstanceOfType(typeof(RequestMessageUrlMatcher)); + } + + [Fact] + public void RequestBuilder_WithUrl_Funcs() + { + // Act + var requestBuilder = (Request) Request.Create().WithUrl(url => true, url => false); + + // Assert + var matchers = requestBuilder.GetPrivateFieldValue>("_requestMatchers"); + Check.That(matchers.Count()).IsEqualTo(1); + Check.That(matchers[0]).IsInstanceOfType(typeof(RequestMessageUrlMatcher)); + } + + [Fact] + public void RequestBuilder_WithUrl_IStringMatchers() + { + // Act + var requestBuilder = (Request) Request.Create().WithUrl(new ExactMatcher("http://a"), new ExactMatcher("http://b")); + + // Assert + var matchers = requestBuilder.GetPrivateFieldValue>("_requestMatchers"); + Check.That(matchers.Count()).IsEqualTo(1); + Check.That(matchers[0]).IsInstanceOfType(typeof(RequestMessageUrlMatcher)); + } + } +} \ No newline at end of file diff --git a/test/WireMock.Net.Tests/RequestCookieTests.cs b/test/WireMock.Net.Tests/RequestCookieTests.cs deleted file mode 100644 index bc1927c2..00000000 --- a/test/WireMock.Net.Tests/RequestCookieTests.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System.Collections.Generic; -using NFluent; -using WireMock.Matchers.Request; -using WireMock.Models; -using WireMock.RequestBuilders; -using Xunit; - -namespace WireMock.Net.Tests -{ - public class RequestCookieTests - { - private const string ClientIp = "::1"; - - [Fact] - public void Request_WithCookie_OK() - { - // given - var spec = Request.Create().UsingAnyMethod().WithCookie("session", "a*"); - - // when - var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "PUT", ClientIp, null, null, new Dictionary { { "session", "abc" } }); - - // then - var requestMatchResult = new RequestMatchResult(); - Check.That(spec.GetMatchingScore(request, requestMatchResult)).IsEqualTo(1.0); - } - } -} \ No newline at end of file diff --git a/test/WireMock.Net.Tests/RequestMatchers/RequestMessageBodyMatcherTests.cs b/test/WireMock.Net.Tests/RequestMatchers/RequestMessageBodyMatcherTests.cs index 2516b68d..6a21a4bb 100644 --- a/test/WireMock.Net.Tests/RequestMatchers/RequestMessageBodyMatcherTests.cs +++ b/test/WireMock.Net.Tests/RequestMatchers/RequestMessageBodyMatcherTests.cs @@ -16,7 +16,8 @@ namespace WireMock.Net.Tests.RequestMatchers // Assign var body = new BodyData { - BodyAsString = "b" + BodyAsString = "b", + DetectedBodyType = BodyType.String }; var stringMatcherMock = new Mock(); stringMatcherMock.Setup(m => m.IsMatch(It.IsAny())).Returns(0.5d); @@ -43,7 +44,8 @@ namespace WireMock.Net.Tests.RequestMatchers // Assign var body = new BodyData { - BodyAsBytes = new byte[] { 1 } + BodyAsBytes = new byte[] { 1 }, + DetectedBodyType = BodyType.Bytes }; var stringMatcherMock = new Mock(); stringMatcherMock.Setup(m => m.IsMatch(It.IsAny())).Returns(0.5d); @@ -70,7 +72,8 @@ namespace WireMock.Net.Tests.RequestMatchers // Assign var body = new BodyData { - BodyAsJson = new { value = 42 } + BodyAsJson = new { value = 42 }, + DetectedBodyType = BodyType.Json }; var stringMatcherMock = new Mock(); stringMatcherMock.Setup(m => m.IsMatch(It.IsAny())).Returns(0.5d); @@ -84,10 +87,10 @@ namespace WireMock.Net.Tests.RequestMatchers double score = matcher.GetMatchingScore(requestMessage, result); // Assert - Check.That(score).IsEqualTo(0.0d); + Check.That(score).IsEqualTo(0.5d); // Verify - stringMatcherMock.Verify(m => m.IsMatch(It.IsAny()), Times.Never); + stringMatcherMock.Verify(m => m.IsMatch(It.IsAny()), Times.Once); } [Fact] @@ -97,7 +100,8 @@ namespace WireMock.Net.Tests.RequestMatchers var body = new BodyData { BodyAsJson = new { value = 42 }, - BodyAsString = "orig" + BodyAsString = "orig", + DetectedBodyType = BodyType.Json }; var stringMatcherMock = new Mock(); stringMatcherMock.Setup(m => m.IsMatch(It.IsAny())).Returns(0.5d); @@ -123,7 +127,8 @@ namespace WireMock.Net.Tests.RequestMatchers // Assign var body = new BodyData { - BodyAsJson = 42 + BodyAsJson = 42, + DetectedBodyType = BodyType.Json }; var objectMatcherMock = new Mock(); objectMatcherMock.Setup(m => m.IsMatch(It.IsAny())).Returns(0.5d); @@ -149,7 +154,8 @@ namespace WireMock.Net.Tests.RequestMatchers // Assign var body = new BodyData { - BodyAsBytes = new byte[] { 1 } + BodyAsBytes = new byte[] { 1 }, + DetectedBodyType = BodyType.Bytes }; var objectMatcherMock = new Mock(); objectMatcherMock.Setup(m => m.IsMatch(It.IsAny())).Returns(0.5d); diff --git a/test/WireMock.Net.Tests/RequestTests.cs b/test/WireMock.Net.Tests/RequestTests.cs index 16f04de4..ee900ffe 100644 --- a/test/WireMock.Net.Tests/RequestTests.cs +++ b/test/WireMock.Net.Tests/RequestTests.cs @@ -35,7 +35,8 @@ namespace WireMock.Net.Tests // when var body = new BodyData { - BodyAsString = "whatever" + BodyAsString = "whatever", + DetectedBodyType = BodyType.String }; var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "PUT", ClientIp, body, new Dictionary { { "X-toto", new[] { "tata" } } }); @@ -53,7 +54,8 @@ namespace WireMock.Net.Tests // when var body = new BodyData { - BodyAsString = "whatever" + BodyAsString = "whatever", + DetectedBodyType = BodyType.String }; var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "PUT", ClientIp, body, new Dictionary { { "X-toto", new[] { "ABC" } } }); @@ -71,7 +73,8 @@ namespace WireMock.Net.Tests // when var body = new BodyData { - BodyAsString = "whatever" + BodyAsString = "whatever", + DetectedBodyType = BodyType.String }; var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "PUT", ClientIp, body, new Dictionary { { "X-toto", new[] { "TaTa" } } }); @@ -89,7 +92,8 @@ namespace WireMock.Net.Tests // when var body = new BodyData { - BodyAsString = "Hello world!" + BodyAsString = "Hello world!", + DetectedBodyType = BodyType.String }; var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "PUT", ClientIp, body); @@ -107,7 +111,8 @@ namespace WireMock.Net.Tests // when var body = new BodyData { - BodyAsString = "xxx" + BodyAsString = "xxx", + DetectedBodyType = BodyType.String }; var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "PUT", ClientIp, body, new Dictionary { { "X-toto", new[] { "tata" } } }); diff --git a/test/WireMock.Net.Tests/RequestWithBodyTests.cs b/test/WireMock.Net.Tests/RequestWithBodyTests.cs index 8b1f47d6..b496851d 100644 --- a/test/WireMock.Net.Tests/RequestWithBodyTests.cs +++ b/test/WireMock.Net.Tests/RequestWithBodyTests.cs @@ -24,7 +24,8 @@ namespace WireMock.Net.Tests // Act var body = new BodyData { - BodyAsString = "b" + BodyAsString = "b", + DetectedBodyType = BodyType.String }; var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "POST", ClientIp, body); @@ -42,7 +43,8 @@ namespace WireMock.Net.Tests // Act var body = new BodyData { - BodyAsJson = 123 + BodyAsJson = 123, + DetectedBodyType = BodyType.Json }; var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "POST", ClientIp, body); @@ -60,7 +62,8 @@ namespace WireMock.Net.Tests // Act var body = new BodyData { - BodyAsBytes = new byte[0] + BodyAsBytes = new byte[0], + DetectedBodyType = BodyType.Bytes }; var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "POST", ClientIp, body); @@ -78,7 +81,8 @@ namespace WireMock.Net.Tests // when var body = new BodyData { - BodyAsString = "cat" + BodyAsString = "cat", + DetectedBodyType = BodyType.String }; var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "POST", ClientIp, body); @@ -96,7 +100,8 @@ namespace WireMock.Net.Tests // when var body = new BodyData { - BodyAsString = "Hello world!" + BodyAsString = "Hello world!", + DetectedBodyType = BodyType.String }; var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "PUT", ClientIp, body); @@ -119,7 +124,8 @@ namespace WireMock.Net.Tests abc def xyz - " + ", + DetectedBodyType = BodyType.String }; var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "PUT", ClientIp, body); @@ -142,7 +148,8 @@ namespace WireMock.Net.Tests abc def xyz - " + ", + DetectedBodyType = BodyType.String }; var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "PUT", ClientIp, body); @@ -160,7 +167,8 @@ namespace WireMock.Net.Tests // when var body = new BodyData { - BodyAsString = "{ \"things\": [ { \"name\": \"RequiredThing\" }, { \"name\": \"Wiremock\" } ] }" + BodyAsString = "{ \"things\": [ { \"name\": \"RequiredThing\" }, { \"name\": \"Wiremock\" } ] }", + DetectedBodyType = BodyType.String }; var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "PUT", ClientIp, body); @@ -178,7 +186,8 @@ namespace WireMock.Net.Tests // when var body = new BodyData { - BodyAsString = "{ \"things\": { \"name\": \"Wiremock\" } }" + BodyAsString = "{ \"things\": { \"name\": \"Wiremock\" } }", + DetectedBodyType = BodyType.String }; var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "PUT", ClientIp, body); @@ -199,7 +208,8 @@ namespace WireMock.Net.Tests { BodyAsJson = JsonConvert.DeserializeObject(jsonString), BodyAsString = jsonString, - Encoding = Encoding.UTF8 + Encoding = Encoding.UTF8, + DetectedBodyType = BodyType.Json }; var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "PUT", ClientIp, bodyData); @@ -221,7 +231,8 @@ namespace WireMock.Net.Tests { BodyAsJson = JsonConvert.DeserializeObject(jsonString), BodyAsString = jsonString, - Encoding = Encoding.UTF8 + Encoding = Encoding.UTF8, + DetectedBodyType = BodyType.Json }; var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "PUT", ClientIp, bodyData); @@ -243,7 +254,8 @@ namespace WireMock.Net.Tests { BodyAsJson = JsonConvert.DeserializeObject(jsonString), BodyAsString = jsonString, - Encoding = Encoding.UTF8 + Encoding = Encoding.UTF8, + DetectedBodyType = BodyType.Json }; var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "PUT", ClientIp, bodyData); @@ -263,7 +275,8 @@ namespace WireMock.Net.Tests var bodyData = new BodyData { - BodyAsJson = DateTime.MinValue + BodyAsJson = DateTime.MinValue, + DetectedBodyType = BodyType.Json }; // Act @@ -283,7 +296,8 @@ namespace WireMock.Net.Tests var bodyData = new BodyData { - BodyAsBytes = new byte[] { 123 } + BodyAsBytes = new byte[] { 123 }, + DetectedBodyType = BodyType.Bytes }; // Act diff --git a/test/WireMock.Net.Tests/RequestWithUrlTests.cs b/test/WireMock.Net.Tests/RequestWithUrlTests.cs deleted file mode 100644 index ae520f4c..00000000 --- a/test/WireMock.Net.Tests/RequestWithUrlTests.cs +++ /dev/null @@ -1,56 +0,0 @@ -using NFluent; -using WireMock.Matchers; -using WireMock.Matchers.Request; -using WireMock.Models; -using WireMock.RequestBuilders; -using Xunit; - -namespace WireMock.Net.Tests -{ - public class RequestWithUrlTests - { - private const string ClientIp = "::1"; - - [Fact] - public void Request_WithUrl() - { - // given - var spec = Request.Create().WithUrl("*/foo"); - - // when - var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "blabla", ClientIp); - - // then - var requestMatchResult = new RequestMatchResult(); - Check.That(spec.GetMatchingScore(request, requestMatchResult)).IsEqualTo(1.0); - } - - [Fact] - public void Request_WithUrl_WildcardMatcher() - { - // given - var spec = Request.Create().WithUrl(new WildcardMatcher("*/foo")); - - // when - var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "blabla", ClientIp); - - // then - var requestMatchResult = new RequestMatchResult(); - Check.That(spec.GetMatchingScore(request, requestMatchResult)).IsEqualTo(1.0); - } - - [Fact] - public void Request_WithUrl_Func() - { - // given - var spec = Request.Create().WithUrl(url => url.Contains("foo")); - - // when - var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "blabla", ClientIp); - - // then - var requestMatchResult = new RequestMatchResult(); - Check.That(spec.GetMatchingScore(request, requestMatchResult)).IsEqualTo(1.0); - } - } -} \ No newline at end of file diff --git a/test/WireMock.Net.Tests/ResponseBuilders/ResponseWithBodyTests.cs b/test/WireMock.Net.Tests/ResponseBuilders/ResponseWithBodyTests.cs index 9b08d8ca..c13d4ac6 100644 --- a/test/WireMock.Net.Tests/ResponseBuilders/ResponseWithBodyTests.cs +++ b/test/WireMock.Net.Tests/ResponseBuilders/ResponseWithBodyTests.cs @@ -18,6 +18,7 @@ namespace WireMock.Net.Tests.ResponseBuilders // given var body = new BodyData { + DetectedBodyType = BodyType.String, BodyAsString = "abc" }; var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "POST", ClientIp, body); @@ -28,9 +29,9 @@ namespace WireMock.Net.Tests.ResponseBuilders var responseMessage = await response.ProvideResponseAsync(request); // then - Check.That(responseMessage.Body).Equals("01"); - Check.That(responseMessage.BodyAsBytes).IsNull(); - Check.That(responseMessage.BodyEncoding).Equals(Encoding.ASCII); + Check.That(responseMessage.BodyData.BodyAsString).Equals("01"); + Check.That(responseMessage.BodyData.BodyAsBytes).IsNull(); + Check.That(responseMessage.BodyData.Encoding).Equals(Encoding.ASCII); } [Fact] @@ -39,6 +40,7 @@ namespace WireMock.Net.Tests.ResponseBuilders // given var body = new BodyData { + DetectedBodyType = BodyType.String, BodyAsString = "abc" }; var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "POST", ClientIp, body); @@ -49,9 +51,9 @@ namespace WireMock.Net.Tests.ResponseBuilders var responseMessage = await response.ProvideResponseAsync(request); // then - Check.That(responseMessage.BodyAsBytes).ContainsExactly(new byte[] { 48, 49 }); - Check.That(responseMessage.Body).IsNull(); - Check.That(responseMessage.BodyEncoding).IsNull(); + Check.That(responseMessage.BodyData.BodyAsBytes).ContainsExactly(new byte[] { 48, 49 }); + Check.That(responseMessage.BodyData.BodyAsString).IsNull(); + Check.That(responseMessage.BodyData.Encoding).IsNull(); } [Fact] @@ -60,6 +62,7 @@ namespace WireMock.Net.Tests.ResponseBuilders // given var body = new BodyData { + DetectedBodyType = BodyType.String, BodyAsString = "abc" }; var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "POST", ClientIp, body); @@ -70,8 +73,8 @@ namespace WireMock.Net.Tests.ResponseBuilders var responseMessage = await response.ProvideResponseAsync(request); // then - Check.That(responseMessage.Body).Equals("test"); - Check.That(responseMessage.BodyEncoding).Equals(Encoding.ASCII); + Check.That(responseMessage.BodyData.BodyAsString).Equals("test"); + Check.That(responseMessage.BodyData.Encoding).Equals(Encoding.ASCII); } [Fact] @@ -80,6 +83,7 @@ namespace WireMock.Net.Tests.ResponseBuilders // given var body = new BodyData { + DetectedBodyType = BodyType.String, BodyAsString = "abc" }; var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "POST", ClientIp, body); @@ -91,9 +95,8 @@ namespace WireMock.Net.Tests.ResponseBuilders var responseMessage = await response.ProvideResponseAsync(request); // then - Check.That(responseMessage.BodyAsJson).IsNotNull(); - Check.That(responseMessage.BodyAsJson).Equals(x); - Check.That(responseMessage.BodyEncoding).Equals(Encoding.ASCII); + Check.That(responseMessage.BodyData.BodyAsJson).Equals(x); + Check.That(responseMessage.BodyData.Encoding).Equals(Encoding.ASCII); } [Fact] @@ -102,6 +105,7 @@ namespace WireMock.Net.Tests.ResponseBuilders // given var body = new BodyData { + DetectedBodyType = BodyType.String, BodyAsString = "abc" }; var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "POST", ClientIp, body); @@ -113,9 +117,8 @@ namespace WireMock.Net.Tests.ResponseBuilders var responseMessage = await response.ProvideResponseAsync(request); // then - Check.That(responseMessage.BodyAsJson).IsNotNull(); - Check.That(responseMessage.BodyAsJson).Equals(x); - Check.That(responseMessage.BodyAsJsonIndented).IsEqualTo(true); + Check.That(responseMessage.BodyData.BodyAsJson).Equals(x); + Check.That(responseMessage.BodyData.BodyAsJsonIndented).IsEqualTo(true); } [Fact] @@ -130,10 +133,10 @@ namespace WireMock.Net.Tests.ResponseBuilders var responseMessage = await response.ProvideResponseAsync(request); // Assert - Check.That(responseMessage.BodyAsBytes).IsNull(); - Check.That(responseMessage.BodyAsJson).IsNull(); - Check.That(responseMessage.Body).Equals("r"); - Check.That(responseMessage.BodyEncoding).Equals(Encoding.ASCII); + Check.That(responseMessage.BodyData.BodyAsBytes).IsNull(); + Check.That(responseMessage.BodyData.BodyAsJson).IsNull(); + Check.That(responseMessage.BodyData.BodyAsString).Equals("r"); + Check.That(responseMessage.BodyData.Encoding).Equals(Encoding.ASCII); } [Fact] @@ -148,10 +151,10 @@ namespace WireMock.Net.Tests.ResponseBuilders var responseMessage = await response.ProvideResponseAsync(request); // Assert - Check.That(responseMessage.Body).IsNull(); - Check.That(responseMessage.BodyAsJson).IsNull(); - Check.That(responseMessage.BodyAsBytes).IsNotNull(); - Check.That(responseMessage.BodyEncoding).Equals(Encoding.ASCII); + Check.That(responseMessage.BodyData.BodyAsString).IsNull(); + Check.That(responseMessage.BodyData.BodyAsJson).IsNull(); + Check.That(responseMessage.BodyData.BodyAsBytes).IsNotNull(); + Check.That(responseMessage.BodyData.Encoding).Equals(Encoding.ASCII); } [Fact] @@ -166,10 +169,10 @@ namespace WireMock.Net.Tests.ResponseBuilders var responseMessage = await response.ProvideResponseAsync(request); // Assert - Check.That(responseMessage.Body).IsNull(); - Check.That(responseMessage.BodyAsBytes).IsNull(); - Check.That(((dynamic)responseMessage.BodyAsJson).value).Equals(42); - Check.That(responseMessage.BodyEncoding).Equals(Encoding.ASCII); + Check.That(responseMessage.BodyData.BodyAsString).IsNull(); + Check.That(responseMessage.BodyData.BodyAsBytes).IsNull(); + Check.That(((dynamic)responseMessage.BodyData.BodyAsJson).value).Equals(42); + Check.That(responseMessage.BodyData.Encoding).Equals(Encoding.ASCII); } [Fact] @@ -188,10 +191,10 @@ namespace WireMock.Net.Tests.ResponseBuilders var responseMessage = await response.ProvideResponseAsync(request); // Assert - Check.That(responseMessage.Body).IsEqualTo("path: /test"); - Check.That(responseMessage.BodyAsBytes).IsNull(); - Check.That(responseMessage.BodyAsJson).IsNull(); - Check.That(responseMessage.BodyEncoding.CodePage).Equals(Encoding.UTF8.CodePage); + Check.That(responseMessage.BodyData.BodyAsString).IsEqualTo("path: /test"); + Check.That(responseMessage.BodyData.BodyAsBytes).IsNull(); + Check.That(responseMessage.BodyData.BodyAsJson).IsNull(); + Check.That(responseMessage.BodyData.Encoding.CodePage).Equals(Encoding.UTF8.CodePage); Check.That(responseMessage.StatusCode).IsEqualTo(500); Check.That(responseMessage.Headers["H1"].ToString()).IsEqualTo("X1"); Check.That(responseMessage.Headers["H2"].ToString()).IsEqualTo("X2"); diff --git a/test/WireMock.Net.Tests/ResponseBuilders/ResponseWithCallbackTests.cs b/test/WireMock.Net.Tests/ResponseBuilders/ResponseWithCallbackTests.cs index dafa07bc..910717c3 100644 --- a/test/WireMock.Net.Tests/ResponseBuilders/ResponseWithCallbackTests.cs +++ b/test/WireMock.Net.Tests/ResponseBuilders/ResponseWithCallbackTests.cs @@ -2,6 +2,7 @@ using NFluent; using WireMock.Models; using WireMock.ResponseBuilders; +using WireMock.Util; using Xunit; namespace WireMock.Net.Tests.ResponseBuilders @@ -13,13 +14,13 @@ namespace WireMock.Net.Tests.ResponseBuilders { // Assign var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "GET", "::1"); - var response = Response.Create().WithCallback(req => new ResponseMessage { Body = req.Path + "Bar", StatusCode = 302 }); + var response = Response.Create().WithCallback(req => new ResponseMessage { BodyData = new BodyData { DetectedBodyType = BodyType.String, BodyAsString = req.Path + "Bar" }, StatusCode = 302 }); // Act var responseMessage = await response.ProvideResponseAsync(request); // Assert - Check.That(responseMessage.Body).IsEqualTo("/fooBar"); + Check.That(responseMessage.BodyData.BodyAsString).IsEqualTo("/fooBar"); Check.That(responseMessage.StatusCode).IsEqualTo(302); } } diff --git a/test/WireMock.Net.Tests/ResponseBuilders/ResponseWithHandlebarsJsonPathTests.cs b/test/WireMock.Net.Tests/ResponseBuilders/ResponseWithHandlebarsJsonPathTests.cs index 89fcbcea..88809e1d 100644 --- a/test/WireMock.Net.Tests/ResponseBuilders/ResponseWithHandlebarsJsonPathTests.cs +++ b/test/WireMock.Net.Tests/ResponseBuilders/ResponseWithHandlebarsJsonPathTests.cs @@ -48,7 +48,8 @@ namespace WireMock.Net.Tests.ResponseBuilders ] } ] - }" + }", + DetectedBodyType = BodyType.String }; var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body); @@ -62,7 +63,7 @@ namespace WireMock.Net.Tests.ResponseBuilders var responseMessage = await response.ProvideResponseAsync(request); // Assert - JObject j = JObject.FromObject(responseMessage.BodyAsJson); + JObject j = JObject.FromObject(responseMessage.BodyData.BodyAsJson); Check.That(j["x"]).IsNotNull(); Check.That(j["x"]["Name"].ToString()).Equals("Acme Co"); } @@ -71,7 +72,11 @@ namespace WireMock.Net.Tests.ResponseBuilders public async Task Response_ProvideResponse_Handlebars_JsonPath_SelectToken_Number_ResponseBodyAsJson() { // Assign - var body = new BodyData { BodyAsString = "{ \"Price\": 99 }" }; + var body = new BodyData + { + BodyAsString = "{ \"Price\": 99 }", + DetectedBodyType = BodyType.String + }; var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body); @@ -84,7 +89,7 @@ namespace WireMock.Net.Tests.ResponseBuilders var responseMessage = await response.ProvideResponseAsync(request); // Assert - JObject j = JObject.FromObject(responseMessage.BodyAsJson); + JObject j = JObject.FromObject(responseMessage.BodyData.BodyAsJson); Check.That(j["x"].Value()).Equals(99); } @@ -123,7 +128,8 @@ namespace WireMock.Net.Tests.ResponseBuilders ] } ] - }" + }", + DetectedBodyType = BodyType.String }; var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body); @@ -137,7 +143,7 @@ namespace WireMock.Net.Tests.ResponseBuilders var responseMessage = await response.ProvideResponseAsync(request); // Assert - Check.That(responseMessage.Body).Equals($"{{{Environment.NewLine} \"Name\": \"Acme Co\",{Environment.NewLine} \"Products\": [{Environment.NewLine} {{{Environment.NewLine} \"Name\": \"Anvil\",{Environment.NewLine} \"Price\": 50{Environment.NewLine} }}{Environment.NewLine} ]{Environment.NewLine}}}"); + Check.That(responseMessage.BodyData.BodyAsString).Equals($"{{{Environment.NewLine} \"Name\": \"Acme Co\",{Environment.NewLine} \"Products\": [{Environment.NewLine} {{{Environment.NewLine} \"Name\": \"Anvil\",{Environment.NewLine} \"Price\": 50{Environment.NewLine} }}{Environment.NewLine} ]{Environment.NewLine}}}"); } [Fact] @@ -175,7 +181,8 @@ namespace WireMock.Net.Tests.ResponseBuilders ] } ] - }") + }"), + DetectedBodyType = BodyType.Json }; var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body); @@ -189,7 +196,7 @@ namespace WireMock.Net.Tests.ResponseBuilders var responseMessage = await response.ProvideResponseAsync(request); // Assert - Check.That(responseMessage.Body).Equals($"{{{Environment.NewLine} \"Name\": \"Acme Co\",{Environment.NewLine} \"Products\": [{Environment.NewLine} {{{Environment.NewLine} \"Name\": \"Anvil\",{Environment.NewLine} \"Price\": 50{Environment.NewLine} }}{Environment.NewLine} ]{Environment.NewLine}}}"); + Check.That(responseMessage.BodyData.BodyAsString).Equals($"{{{Environment.NewLine} \"Name\": \"Acme Co\",{Environment.NewLine} \"Products\": [{Environment.NewLine} {{{Environment.NewLine} \"Name\": \"Anvil\",{Environment.NewLine} \"Price\": 50{Environment.NewLine} }}{Environment.NewLine} ]{Environment.NewLine}}}"); } [Fact] @@ -227,7 +234,8 @@ namespace WireMock.Net.Tests.ResponseBuilders ] } ] - }" + }", + DetectedBodyType = BodyType.String }; var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body); @@ -241,7 +249,7 @@ namespace WireMock.Net.Tests.ResponseBuilders var responseMessage = await response.ProvideResponseAsync(request); // Assert - Check.That(responseMessage.Body).Equals("%0:Anvil%%1:Elbow Grease%"); + Check.That(responseMessage.BodyData.BodyAsString).Equals("%0:Anvil%%1:Elbow Grease%"); } [Fact] @@ -279,7 +287,8 @@ namespace WireMock.Net.Tests.ResponseBuilders ] } ] - }") + }"), + DetectedBodyType = BodyType.Json }; var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body); @@ -293,7 +302,7 @@ namespace WireMock.Net.Tests.ResponseBuilders var responseMessage = await response.ProvideResponseAsync(request); // Assert - Check.That(responseMessage.Body).Equals("%0:Anvil%%1:Elbow Grease%"); + Check.That(responseMessage.BodyData.BodyAsString).Equals("%0:Anvil%%1:Elbow Grease%"); } [Fact] @@ -307,7 +316,8 @@ namespace WireMock.Net.Tests.ResponseBuilders 'Lambton Quay', 'Willis Street' ] - }") + }"), + DetectedBodyType = BodyType.Json }; var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body); diff --git a/test/WireMock.Net.Tests/ResponseBuilders/ResponseWithHandlebarsLinqTests.cs b/test/WireMock.Net.Tests/ResponseBuilders/ResponseWithHandlebarsLinqTests.cs index f8fe1e8a..f43e8110 100644 --- a/test/WireMock.Net.Tests/ResponseBuilders/ResponseWithHandlebarsLinqTests.cs +++ b/test/WireMock.Net.Tests/ResponseBuilders/ResponseWithHandlebarsLinqTests.cs @@ -28,7 +28,7 @@ namespace WireMock.Net.Tests.ResponseBuilders var responseMessage = await response.ProvideResponseAsync(request); // Assert - JObject j = JObject.FromObject(responseMessage.BodyAsJson); + JObject j = JObject.FromObject(responseMessage.BodyData.BodyAsJson); Check.That(j["x"]).IsNotNull(); Check.That(j["x"].ToString()).Equals("/pathtest"); } @@ -43,7 +43,8 @@ namespace WireMock.Net.Tests.ResponseBuilders { { "Id", new JValue(9) }, { "Name", new JValue("Test") } - } + }, + DetectedBodyType = BodyType.Json }; var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", "::1", body); @@ -57,7 +58,7 @@ namespace WireMock.Net.Tests.ResponseBuilders var responseMessage = await response.ProvideResponseAsync(request); // Assert - JObject j = JObject.FromObject(responseMessage.BodyAsJson); + JObject j = JObject.FromObject(responseMessage.BodyData.BodyAsJson); Check.That(j["x"]).IsNotNull(); Check.That(j["x"].ToString()).Equals("Test_123"); } @@ -72,7 +73,8 @@ namespace WireMock.Net.Tests.ResponseBuilders { { "Id", new JValue(9) }, { "Name", new JValue("Test") } - } + }, + DetectedBodyType = BodyType.Json }; var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", "::1", body); @@ -86,7 +88,7 @@ namespace WireMock.Net.Tests.ResponseBuilders var responseMessage = await response.ProvideResponseAsync(request); // Assert - JObject j = JObject.FromObject(responseMessage.BodyAsJson); + JObject j = JObject.FromObject(responseMessage.BodyData.BodyAsJson); Check.That(j["x"]).IsNotNull(); Check.That(j["x"].ToString()).Equals("{ N = Test_123, I = 9 }"); } @@ -101,7 +103,8 @@ namespace WireMock.Net.Tests.ResponseBuilders { { "Id", new JValue(9) }, { "Name", new JValue("Test") } - } + }, + DetectedBodyType = BodyType.Json }; var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", "::1", body); @@ -115,7 +118,7 @@ namespace WireMock.Net.Tests.ResponseBuilders var responseMessage = await response.ProvideResponseAsync(request); // Assert - JObject j = JObject.FromObject(responseMessage.BodyAsJson); + JObject j = JObject.FromObject(responseMessage.BodyData.BodyAsJson); Check.That(j["x"]).IsNotNull(); Check.That(j["x"].ToString()).Equals("{ N = Test_123, I = 9 }"); } @@ -124,7 +127,11 @@ namespace WireMock.Net.Tests.ResponseBuilders public void Response_ProvideResponse_Handlebars_Linq_Throws_NotSupportedException() { // Assign - var body = new BodyData { BodyAsJson = new { x = "x" }}; + var body = new BodyData + { + BodyAsJson = new { x = "x" }, + DetectedBodyType = BodyType.Json + }; var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", "::1", body); @@ -178,7 +185,8 @@ namespace WireMock.Net.Tests.ResponseBuilders { { "Id", new JValue(9) }, { "Name", new JValue("Test") } - } + }, + DetectedBodyType = BodyType.Json }; var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", "::1", body); @@ -191,7 +199,7 @@ namespace WireMock.Net.Tests.ResponseBuilders var responseMessage = await response.ProvideResponseAsync(request); // Assert - JObject j = JObject.FromObject(responseMessage.BodyAsJson); + JObject j = JObject.FromObject(responseMessage.BodyData.BodyAsJson); Check.That(j["x"].ToString()).IsEmpty(); } @@ -205,7 +213,8 @@ namespace WireMock.Net.Tests.ResponseBuilders { { "Id", new JValue(9) }, { "Name", new JValue("Test") } - } + }, + DetectedBodyType = BodyType.Json }; var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", "::1", body); @@ -218,7 +227,7 @@ namespace WireMock.Net.Tests.ResponseBuilders var responseMessage = await response.ProvideResponseAsync(request); // Assert - JObject j = JObject.FromObject(responseMessage.BodyAsJson); + JObject j = JObject.FromObject(responseMessage.BodyData.BodyAsJson); Check.That(j["x"].ToString()).IsEmpty(); } } diff --git a/test/WireMock.Net.Tests/ResponseBuilders/ResponseWithHandlebarsRegexTests.cs b/test/WireMock.Net.Tests/ResponseBuilders/ResponseWithHandlebarsRegexTests.cs index 8f06ddf2..1192c7ec 100644 --- a/test/WireMock.Net.Tests/ResponseBuilders/ResponseWithHandlebarsRegexTests.cs +++ b/test/WireMock.Net.Tests/ResponseBuilders/ResponseWithHandlebarsRegexTests.cs @@ -15,7 +15,7 @@ namespace WireMock.Net.Tests.ResponseBuilders public async void Response_ProvideResponse_Handlebars_RegexMatch() { // Assign - var body = new BodyData { BodyAsString = "abc" }; + var body = new BodyData { BodyAsString = "abc", DetectedBodyType = BodyType.String }; var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body); @@ -27,14 +27,14 @@ namespace WireMock.Net.Tests.ResponseBuilders var responseMessage = await response.ProvideResponseAsync(request); // assert - Check.That(responseMessage.Body).Equals("abc"); + Check.That(responseMessage.BodyData.BodyAsString).Equals("abc"); } [Fact] public async void Response_ProvideResponse_Handlebars_RegexMatch_NoMatch() { // Assign - var body = new BodyData { BodyAsString = "abc" }; + var body = new BodyData { BodyAsString = "abc", DetectedBodyType = BodyType.String }; var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body); @@ -46,14 +46,14 @@ namespace WireMock.Net.Tests.ResponseBuilders var responseMessage = await response.ProvideResponseAsync(request); // assert - Check.That(responseMessage.Body).Equals(""); + Check.That(responseMessage.BodyData.BodyAsString).Equals(""); } [Fact] public async void Response_ProvideResponse_Handlebars_RegexMatch_NoMatch_WithDefaultValue() { // Assign - var body = new BodyData { BodyAsString = "abc" }; + var body = new BodyData { BodyAsString = "abc", DetectedBodyType = BodyType.String }; var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body); @@ -65,14 +65,14 @@ namespace WireMock.Net.Tests.ResponseBuilders var responseMessage = await response.ProvideResponseAsync(request); // assert - Check.That(responseMessage.Body).Equals("d"); + Check.That(responseMessage.BodyData.BodyAsString).Equals("d"); } [Fact] public async void Response_ProvideResponse_Handlebars_RegexMatch2() { // Assign - var body = new BodyData { BodyAsString = "https://localhost:5000/" }; + var body = new BodyData { BodyAsString = "https://localhost:5000/", DetectedBodyType = BodyType.String }; var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body); @@ -84,14 +84,14 @@ namespace WireMock.Net.Tests.ResponseBuilders var responseMessage = await response.ProvideResponseAsync(request); // assert - Check.That(responseMessage.Body).Equals("5000-https"); + Check.That(responseMessage.BodyData.BodyAsString).Equals("5000-https"); } [Fact] public async void Response_ProvideResponse_Handlebars_RegexMatch2_NoMatch() { // Assign - var body = new BodyData { BodyAsString = "{{\\test" }; + var body = new BodyData { BodyAsString = "{{\\test", DetectedBodyType = BodyType.String }; var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body); @@ -103,14 +103,14 @@ namespace WireMock.Net.Tests.ResponseBuilders var responseMessage = await response.ProvideResponseAsync(request); // assert - Check.That(responseMessage.Body).Equals(""); + Check.That(responseMessage.BodyData.BodyAsString).Equals(""); } [Fact] public async void Response_ProvideResponse_Handlebars_RegexMatch2_NoMatch_WithDefaultValue() { // Assign - var body = new BodyData { BodyAsString = "{{\\test" }; + var body = new BodyData { BodyAsString = "{{\\test", DetectedBodyType = BodyType.String }; var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body); @@ -122,14 +122,14 @@ namespace WireMock.Net.Tests.ResponseBuilders var responseMessage = await response.ProvideResponseAsync(request); // assert - Check.That(responseMessage.Body).Equals("x"); + Check.That(responseMessage.BodyData.BodyAsString).Equals("x"); } [Fact] public void Response_ProvideResponse_Handlebars_RegexMatch2_Throws() { // Assign - var body = new BodyData { BodyAsString = "{{\\test" }; + var body = new BodyData { BodyAsString = "{{\\test", DetectedBodyType = BodyType.String }; var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body); diff --git a/test/WireMock.Net.Tests/ResponseBuilders/ResponseWithHandlebarsTests.cs b/test/WireMock.Net.Tests/ResponseBuilders/ResponseWithHandlebarsTests.cs index cefcd1c1..d609be14 100644 --- a/test/WireMock.Net.Tests/ResponseBuilders/ResponseWithHandlebarsTests.cs +++ b/test/WireMock.Net.Tests/ResponseBuilders/ResponseWithHandlebarsTests.cs @@ -28,6 +28,7 @@ namespace WireMock.Net.Tests.ResponseBuilders var bodyData = new BodyData { BodyAsJson = JsonConvert.DeserializeObject(jsonString), + DetectedBodyType = BodyType.Json, Encoding = Encoding.UTF8 }; var request = new RequestMessage(new UrlDetails("http://localhost/foo_object"), "POST", ClientIp, bodyData); @@ -40,7 +41,7 @@ namespace WireMock.Net.Tests.ResponseBuilders var responseMessage = await response.ProvideResponseAsync(request); // Assert - Check.That(JsonConvert.SerializeObject(responseMessage.BodyAsJson)).Equals("{\"x\":\"test /foo_object\"}"); + Check.That(JsonConvert.SerializeObject(responseMessage.BodyData.BodyAsJson)).Equals("{\"x\":\"test /foo_object\"}"); } [Fact] @@ -49,7 +50,8 @@ namespace WireMock.Net.Tests.ResponseBuilders // Assign var body = new BodyData { - BodyAsString = "whatever" + BodyAsString = "whatever", + DetectedBodyType = BodyType.String }; var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "POSt", ClientIp, body); @@ -61,7 +63,7 @@ namespace WireMock.Net.Tests.ResponseBuilders var responseMessage = await response.ProvideResponseAsync(request); // Assert - Check.That(responseMessage.Body).Equals("test http://localhost/foo /foo POSt"); + Check.That(responseMessage.BodyData.BodyAsString).Equals("test http://localhost/foo /foo POSt"); } [Fact] @@ -79,7 +81,7 @@ namespace WireMock.Net.Tests.ResponseBuilders var responseMessage = await response.ProvideResponseAsync(request); // Assert - Check.That(responseMessage.Body).Equals("http://localhost/a/b http://localhost/wiremock/a/b /a/b /wiremock/a/b"); + Check.That(responseMessage.BodyData.BodyAsString).Equals("http://localhost/a/b http://localhost/wiremock/a/b /a/b /wiremock/a/b"); } [Fact] @@ -97,7 +99,7 @@ namespace WireMock.Net.Tests.ResponseBuilders var responseMessage = await response.ProvideResponseAsync(request); // Assert - Check.That(responseMessage.Body).Equals("a wiremock"); + Check.That(responseMessage.BodyData.BodyAsString).Equals("a wiremock"); } [Fact] @@ -106,7 +108,8 @@ namespace WireMock.Net.Tests.ResponseBuilders // Assign var body = new BodyData { - BodyAsString = "abc" + BodyAsString = "abc", + DetectedBodyType = BodyType.String }; var request = new RequestMessage(new UrlDetails("http://localhost/foo?a=1&a=2&b=5"), "POST", ClientIp, body); @@ -118,7 +121,7 @@ namespace WireMock.Net.Tests.ResponseBuilders var responseMessage = await response.ProvideResponseAsync(request); // Assert - Check.That(responseMessage.Body).Equals("test keya=1 idx=1 idx=2 keyb=5"); + Check.That(responseMessage.BodyData.BodyAsString).Equals("test keya=1 idx=1 idx=2 keyb=5"); } [Fact] @@ -127,7 +130,8 @@ namespace WireMock.Net.Tests.ResponseBuilders // Assign var body = new BodyData { - BodyAsString = "abc" + BodyAsString = "abc", + DetectedBodyType = BodyType.String }; var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "POST", ClientIp, body, new Dictionary { { "Content-Type", new[] { "text/plain" } } }); @@ -137,7 +141,7 @@ namespace WireMock.Net.Tests.ResponseBuilders var responseMessage = await response.ProvideResponseAsync(request); // Assert - Check.That(responseMessage.Body).Equals("test"); + Check.That(responseMessage.BodyData.BodyAsString).Equals("test"); Check.That(responseMessage.Headers).ContainsKey("x"); Check.That(responseMessage.Headers["x"]).ContainsExactly("text/plain"); } @@ -148,7 +152,8 @@ namespace WireMock.Net.Tests.ResponseBuilders // Assign var body = new BodyData { - BodyAsString = "abc" + BodyAsString = "abc", + DetectedBodyType = BodyType.String }; var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "POST", ClientIp, body, new Dictionary { { "Content-Type", new[] { "text/plain" } } }); @@ -158,7 +163,7 @@ namespace WireMock.Net.Tests.ResponseBuilders var responseMessage = await response.ProvideResponseAsync(request); // Assert - Check.That(responseMessage.Body).Equals("test"); + Check.That(responseMessage.BodyData.BodyAsString).Equals("test"); Check.That(responseMessage.Headers).ContainsKey("x"); Check.That(responseMessage.Headers["x"]).Contains("text/plain"); Check.That(responseMessage.Headers["x"]).Contains("http://localhost/foo"); @@ -170,7 +175,8 @@ namespace WireMock.Net.Tests.ResponseBuilders // Assign var body = new BodyData { - BodyAsString = "abc" + BodyAsString = "abc", + DetectedBodyType = BodyType.String }; var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body); @@ -182,7 +188,7 @@ namespace WireMock.Net.Tests.ResponseBuilders var responseMessage = await response.ProvideResponseAsync(request); // Assert - Check.That(responseMessage.Body).Equals("test http://localhost:1234 1234 http localhost"); + Check.That(responseMessage.BodyData.BodyAsString).Equals("test http://localhost:1234 1234 http localhost"); } [Fact] @@ -193,6 +199,7 @@ namespace WireMock.Net.Tests.ResponseBuilders var bodyData = new BodyData { BodyAsJson = JsonConvert.DeserializeObject(jsonString), + DetectedBodyType = BodyType.Json, Encoding = Encoding.UTF8 }; var request = new RequestMessage(new UrlDetails("http://localhost/foo_array"), "POST", ClientIp, bodyData); @@ -205,7 +212,7 @@ namespace WireMock.Net.Tests.ResponseBuilders var responseMessage = await response.ProvideResponseAsync(request); // Assert - Check.That(JsonConvert.SerializeObject(responseMessage.BodyAsJson)).Equals("[\"first\",\"/foo_array\",\"test 1\",\"test 2\",\"last\"]"); + Check.That(JsonConvert.SerializeObject(responseMessage.BodyData.BodyAsJson)).Equals("[\"first\",\"/foo_array\",\"test 1\",\"test 2\",\"last\"]"); } } } \ No newline at end of file diff --git a/test/WireMock.Net.Tests/ResponseBuilders/ResponseWithHeadersTests.cs b/test/WireMock.Net.Tests/ResponseBuilders/ResponseWithHeadersTests.cs index 404efbb4..ad596373 100644 --- a/test/WireMock.Net.Tests/ResponseBuilders/ResponseWithHeadersTests.cs +++ b/test/WireMock.Net.Tests/ResponseBuilders/ResponseWithHeadersTests.cs @@ -12,6 +12,39 @@ namespace WireMock.Net.Tests.ResponseBuilders { private const string ClientIp = "::1"; + [Theory] + [InlineData("Content-Length", "1024")] + [InlineData("Transfer-Encoding", "identity")] + [InlineData("Location", "http://test")] + public async Task Response_ProvideResponse_WithHeader_SingleValue(string headerName, string headerValue) + { + // Assign + var requestMock = new RequestMessage(new UrlDetails("http://localhost/foo"), "PUT", ClientIp); + IResponseBuilder builder = Response.Create().WithHeader(headerName, headerValue); + + // Act + var response = await builder.ProvideResponseAsync(requestMock); + + // Assert + Check.That(response.Headers[headerName].ToString()).Equals(headerValue); + } + + [Theory] + [InlineData("Test", new[] { "one" })] + [InlineData("Test", new[] { "a", "b" })] + public async Task Response_ProvideResponse_WithHeader_MultipleValues(string headerName, string[] headerValues) + { + // Assign + var requestMock = new RequestMessage(new UrlDetails("http://localhost/foo"), "PUT", ClientIp); + IResponseBuilder builder = Response.Create().WithHeader(headerName, headerValues); + + // Act + var response = await builder.ProvideResponseAsync(requestMock); + + // Assert + Check.That(response.Headers[headerName].ToArray()).Equals(headerValues); + } + [Fact] public async Task Response_ProvideResponse_WithHeaders_SingleValue() { diff --git a/test/WireMock.Net.Tests/ResponseBuilders/ResponseWithProxyTests.cs b/test/WireMock.Net.Tests/ResponseBuilders/ResponseWithProxyTests.cs index 25ced092..28b3aafb 100644 --- a/test/WireMock.Net.Tests/ResponseBuilders/ResponseWithProxyTests.cs +++ b/test/WireMock.Net.Tests/ResponseBuilders/ResponseWithProxyTests.cs @@ -30,14 +30,14 @@ namespace WireMock.Net.Tests.ResponseBuilders { // Assign var headers = new Dictionary { { "Content-Type", new[] { "application/xml" } } }; - var request = new RequestMessage(new UrlDetails($"{_server.Urls[0]}/{_guid}"), "POST", "::1", new BodyData { BodyAsJson = new { a = 1 } }, headers); + var request = new RequestMessage(new UrlDetails($"{_server.Urls[0]}/{_guid}"), "POST", "::1", new BodyData { DetectedBodyType = BodyType.Json, BodyAsJson = new { a = 1 } }, headers); var response = Response.Create().WithProxy(_server.Urls[0]); // Act var responseMessage = await response.ProvideResponseAsync(request); // Assert - Check.That(responseMessage.Body).IsEqualTo("{\"p\":42}"); + Check.That(responseMessage.BodyData.BodyAsString).IsEqualTo("{\"p\":42}"); Check.That(responseMessage.StatusCode).IsEqualTo(201); Check.That(responseMessage.Headers["Content-Type"].ToString()).IsEqualTo("application/json"); } diff --git a/test/WireMock.Net.Tests/ResponseTests.cs b/test/WireMock.Net.Tests/ResponseTests.cs deleted file mode 100644 index a25cb819..00000000 --- a/test/WireMock.Net.Tests/ResponseTests.cs +++ /dev/null @@ -1,29 +0,0 @@ -using NFluent; -using WireMock.Models; -using WireMock.ResponseBuilders; -using Xunit; - -namespace WireMock.Net.Tests -{ - public class ResponseTests - { - private const string ClientIp = "::1"; - - [Theory] - [InlineData("Content-Length", "1024")] - [InlineData("Transfer-Encoding", "identity")] - [InlineData("Location", "http://test")] - public async void Response_Create_WithHeader(string headerName, string headerValue) - { - // Assign - var requestMock = new RequestMessage(new UrlDetails("http://localhost/foo"), "PUT", ClientIp); - IResponseBuilder builder = Response.Create().WithHeader(headerName, headerValue); - - // Act - var response = await builder.ProvideResponseAsync(requestMock); - - // Assert - Check.That(response.Headers[headerName].ToString()).Equals(headerValue); - } - } -} \ No newline at end of file diff --git a/test/WireMock.Net.Tests/Serialization/LogEntryMapperTests.cs b/test/WireMock.Net.Tests/Serialization/LogEntryMapperTests.cs new file mode 100644 index 00000000..3552cb99 --- /dev/null +++ b/test/WireMock.Net.Tests/Serialization/LogEntryMapperTests.cs @@ -0,0 +1,92 @@ +using NFluent; +using WireMock.Logging; +using WireMock.Models; +using WireMock.Serialization; +using WireMock.Util; +using Xunit; + +namespace WireMock.Net.Tests.Serialization +{ + public class LogEntryMapperTests + { + [Fact] + public void LogEntryMapper_Map_LogEntry_Check_BodyTypeBytes() + { + // Assign + var logEntry = new LogEntry + { + RequestMessage = new RequestMessage( + new UrlDetails("http://localhost"), + "post", + "::1", + new BodyData + { + DetectedBodyType = BodyType.Bytes, + BodyAsBytes = new byte[] { 0 } + } + ), + ResponseMessage = new ResponseMessage + { + BodyData = new BodyData + { + DetectedBodyType = BodyType.Bytes, + BodyAsBytes = new byte[] { 0 } + } + } + }; + + // Act + var result = LogEntryMapper.Map(logEntry); + + // Assert + Check.That(result.Request.DetectedBodyType).IsEqualTo("Bytes"); + Check.That(result.Request.DetectedBodyTypeFromContentType).IsEqualTo("None"); + Check.That(result.Request.BodyAsBytes).ContainsExactly(new byte[] { 0 }); + Check.That(result.Request.Body).IsNull(); + Check.That(result.Request.BodyAsJson).IsNull(); + + Check.That(result.Response.DetectedBodyType).IsEqualTo(BodyType.Bytes); + Check.That(result.Response.DetectedBodyTypeFromContentType).IsEqualTo(BodyType.None); + Check.That(result.Response.BodyAsBytes).ContainsExactly(new byte[] { 0 }); + Check.That(result.Response.Body).IsNull(); + Check.That(result.Response.BodyAsJson).IsNull(); + Check.That(result.Response.BodyAsFile).IsNull(); + } + + [Fact] + public void LogEntryMapper_Map_LogEntry_Check_ResponseBodyTypeFile() + { + // 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" + } + } + }; + + // Act + var result = LogEntryMapper.Map(logEntry); + + // Assert + Check.That(result.Request.DetectedBodyType).IsNull(); + Check.That(result.Request.DetectedBodyTypeFromContentType).IsNull(); + Check.That(result.Request.BodyAsBytes).IsNull(); + Check.That(result.Request.Body).IsNull(); + Check.That(result.Request.BodyAsJson).IsNull(); + + Check.That(result.Response.DetectedBodyType).IsEqualTo(BodyType.File); + Check.That(result.Response.DetectedBodyTypeFromContentType).IsEqualTo(BodyType.None); + Check.That(result.Request.BodyAsBytes).IsNull(); + Check.That(result.Response.Body).IsNull(); + Check.That(result.Response.BodyAsJson).IsNull(); + Check.That(result.Response.BodyAsFile).IsEqualTo("test"); + } + } +} \ No newline at end of file diff --git a/test/WireMock.Net.Tests/Serialization/MatcherMapperTests.cs b/test/WireMock.Net.Tests/Serialization/MatcherMapperTests.cs index fd306031..d74775b7 100644 --- a/test/WireMock.Net.Tests/Serialization/MatcherMapperTests.cs +++ b/test/WireMock.Net.Tests/Serialization/MatcherMapperTests.cs @@ -1,5 +1,7 @@ -using Moq; +using System; +using Moq; using NFluent; +using WireMock.Admin.Mappings; using WireMock.Matchers; using WireMock.Serialization; using Xunit; @@ -36,7 +38,7 @@ namespace WireMock.Net.Tests.Serialization var matcherMock2 = new Mock(); // Act - var models = MatcherMapper.Map(new [] { matcherMock1.Object, matcherMock2.Object }); + var models = MatcherMapper.Map(new[] { matcherMock1.Object, matcherMock2.Object }); // Assert Check.That(models).HasSize(2); @@ -73,5 +75,61 @@ namespace WireMock.Net.Tests.Serialization // Assert Check.That(model.IgnoreCase).Equals(true); } + + [Fact] + public void MatcherMapper_Map_MatcherModel_Null() + { + // Act + var result = MatcherMapper.Map((MatcherModel)null); + + // Assert + Check.That(result).IsNull(); + } + + [Fact] + public void MatcherMapper_Map_MatcherModel_Exception() + { + // Assign + var model = new MatcherModel { Name = "test" }; + + // Act and Assert + Check.ThatCode(() => MatcherMapper.Map(model)).Throws(); + } + + [Fact] + public void MatcherMapper_Map_MatcherModel_LinqMatcher_Pattern() + { + // Assign + var model = new MatcherModel + { + Name = "LinqMatcher", + Pattern = "p" + }; + + // Act + var matcher = (LinqMatcher)MatcherMapper.Map(model); + + // Assert + Check.That(matcher.MatchBehaviour).IsEqualTo(MatchBehaviour.AcceptOnMatch); + Check.That(matcher.GetPatterns()).ContainsExactly("p"); + } + + [Fact] + public void MatcherMapper_Map_MatcherModel_LinqMatcher_Patterns() + { + // Assign + var model = new MatcherModel + { + Name = "LinqMatcher", + Patterns = new[] { "p1", "p2" } + }; + + // Act + var matcher = (LinqMatcher)MatcherMapper.Map(model); + + // Assert + Check.That(matcher.MatchBehaviour).IsEqualTo(MatchBehaviour.AcceptOnMatch); + Check.That(matcher.GetPatterns()).ContainsExactly("p1", "p2"); + } } } \ No newline at end of file diff --git a/test/WireMock.Net.Tests/Util/BodyParserTests.cs b/test/WireMock.Net.Tests/Util/BodyParserTests.cs index bafcc5a9..a6e2da14 100644 --- a/test/WireMock.Net.Tests/Util/BodyParserTests.cs +++ b/test/WireMock.Net.Tests/Util/BodyParserTests.cs @@ -9,49 +9,63 @@ namespace WireMock.Net.Tests.Util { public class BodyParserTests { - [Fact] - public async Task BodyParser_Parse_ApplicationJson() + [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) { // Assign - var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes("{ \"x\": 1 }")); + var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(bodyAsJson)); // Act - var body = await BodyParser.Parse(memoryStream, "application/json"); + var body = await BodyParser.Parse(memoryStream, contentType); // Assert - Check.That(body.BodyAsBytes).IsNull(); + Check.That(body.BodyAsBytes).IsNotNull(); Check.That(body.BodyAsJson).IsNotNull(); - Check.That(body.BodyAsString).Equals("{ \"x\": 1 }"); + Check.That(body.BodyAsString).Equals(bodyAsJson); + Check.That(body.DetectedBodyType).IsEqualTo(detectedBodyType); + Check.That(body.DetectedBodyTypeFromContentType).IsEqualTo(detectedBodyTypeFromContentType); } - [Fact] // http://jsonapi.org/ - public async Task BodyParser_Parse_ApplicationJsonApi() + [Theory] + [InlineData("application/xml", "hello", 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) { // Assign - var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes("{ \"x\": 1 }")); + var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(bodyAsString)); // Act - var body = await BodyParser.Parse(memoryStream, "application/vnd.api+json"); + var body = await BodyParser.Parse(memoryStream, contentType); // Assert - Check.That(body.BodyAsBytes).IsNull(); - Check.That(body.BodyAsJson).IsNotNull(); - Check.That(body.BodyAsString).Equals("{ \"x\": 1 }"); - } - - [Fact] - public async Task BodyParser_Parse_ApplicationXml() - { - // Assign - var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes("hello")); - - // Act - var body = await BodyParser.Parse(memoryStream, "application/xml; charset=UTF-8"); - - // Assert - Check.That(body.BodyAsBytes).IsNull(); + Check.That(body.BodyAsBytes).IsNotNull(); Check.That(body.BodyAsJson).IsNull(); - Check.That(body.BodyAsString).Equals("hello"); + Check.That(body.BodyAsString).Equals(bodyAsString); + Check.That(body.DetectedBodyType).IsEqualTo(detectedBodyType); + Check.That(body.DetectedBodyTypeFromContentType).IsEqualTo(detectedBodyTypeFromContentType); + } + + [Theory] + [InlineData(null, "hello", BodyType.String, BodyType.Bytes)] + public async Task BodyParser_Parse_ContentTypeIsNull(string contentType, string bodyAsString, BodyType detectedBodyType, BodyType detectedBodyTypeFromContentType) + { + // Assign + 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); } } } \ No newline at end of file diff --git a/test/WireMock.Net.Tests/WireMock.Net.Tests.csproj b/test/WireMock.Net.Tests/WireMock.Net.Tests.csproj index 30d832e5..2eda1787 100644 --- a/test/WireMock.Net.Tests/WireMock.Net.Tests.csproj +++ b/test/WireMock.Net.Tests/WireMock.Net.Tests.csproj @@ -14,6 +14,7 @@ + @@ -27,17 +28,19 @@ all runtime; build; native; contentfiles; analyzers + + + - + -