diff --git a/src/WireMock.Net.Abstractions/Admin/Mappings/StatusModel.cs b/src/WireMock.Net.Abstractions/Admin/Mappings/StatusModel.cs index a050999b..348e36bd 100644 --- a/src/WireMock.Net.Abstractions/Admin/Mappings/StatusModel.cs +++ b/src/WireMock.Net.Abstractions/Admin/Mappings/StatusModel.cs @@ -1,21 +1,25 @@ -using System; +using System; -namespace WireMock.Admin.Mappings +namespace WireMock.Admin.Mappings; + +/// +/// Status +/// +[FluentBuilder.AutoGenerateBuilder] +public class StatusModel { /// - /// Status + /// The optional guid. /// - [FluentBuilder.AutoGenerateBuilder] - public class StatusModel - { - /// - /// The optional guid. - /// - public Guid? Guid { get; set; } + public Guid? Guid { get; set; } - /// - /// The status (can also contain the error message). - /// - public string Status { get; set; } - } + /// + /// The status. + /// + public string? Status { get; set; } + + /// + /// The error message. + /// + public string? Error { get; set; } } \ No newline at end of file diff --git a/src/WireMock.Net.Abstractions/Admin/Settings/SettingsModel.cs b/src/WireMock.Net.Abstractions/Admin/Settings/SettingsModel.cs index 81dd5e14..9f02d969 100644 --- a/src/WireMock.Net.Abstractions/Admin/Settings/SettingsModel.cs +++ b/src/WireMock.Net.Abstractions/Admin/Settings/SettingsModel.cs @@ -62,11 +62,6 @@ public class SettingsModel /// public bool? HandleRequestsSynchronously { get; set; } - /// - /// Throw an exception when the Matcher fails because of invalid input. (default set to false). - /// - public bool? ThrowExceptionWhenMatcherFails { get; set; } - /// /// Use the RegexExtended instead of the default . (default set to true). /// diff --git a/src/WireMock.Net.Abstractions/Handlers/IFileSystemHandler.cs b/src/WireMock.Net.Abstractions/Handlers/IFileSystemHandler.cs index dd0516cb..66c31e84 100644 --- a/src/WireMock.Net.Abstractions/Handlers/IFileSystemHandler.cs +++ b/src/WireMock.Net.Abstractions/Handlers/IFileSystemHandler.cs @@ -1,121 +1,120 @@ using JetBrains.Annotations; using System.Collections.Generic; -namespace WireMock.Handlers +namespace WireMock.Handlers; + +/// +/// Handler to interact with the file system to handle folders and read and write (static mapping) files. +/// +public interface IFileSystemHandler { /// - /// Handler to interact with the file system to handle folders and read and write (static mapping) files. + /// Gets the folder where the static mappings are located. For local file system, this would be `{CurrentFolder}/__admin/mappings`. /// - public interface IFileSystemHandler - { - /// - /// Gets the folder where the static mappings are located. For local file system, this would be `{CurrentFolder}/__admin/mappings`. - /// - /// The folder name. - string GetMappingFolder(); + /// The folder name. + string GetMappingFolder(); - /// - /// Determines whether the given path refers to an existing directory on disk. - /// - /// The path. - /// true if path refers to an existing directory; false if the directory does not exist or an error occurs when trying to determine if the specified directory exists. - bool FolderExists([NotNull] string path); + /// + /// Determines whether the given path refers to an existing directory on disk. + /// + /// The path. + /// true if path refers to an existing directory; false if the directory does not exist or an error occurs when trying to determine if the specified directory exists. + bool FolderExists([NotNull] string path); - /// - /// Creates all directories and subdirectories in the specified path unless they already exist. - /// - /// The path. - void CreateFolder([NotNull] string path); + /// + /// Creates all directories and subdirectories in the specified path unless they already exist. + /// + /// The path. + void CreateFolder([NotNull] string path); - /// - /// Returns an enumerable collection of file names in a specified path. - /// - /// The path. - /// A value indicating whether subdirectories should also included when enumerating files. - /// An enumerable collection of the full names (including paths) for the files in the directory (and optionally subdirectories) specified by path. - IEnumerable EnumerateFiles([NotNull] string path, bool includeSubdirectories); + /// + /// Returns an enumerable collection of file names in a specified path. + /// + /// The path. + /// A value indicating whether subdirectories should also included when enumerating files. + /// An enumerable collection of the full names (including paths) for the files in the directory (and optionally subdirectories) specified by path. + IEnumerable EnumerateFiles([NotNull] string path, bool includeSubdirectories); - /// - /// Read a static mapping file as text. - /// - /// The path (folder + filename with .json extension). - /// The file content as text. - string ReadMappingFile([NotNull] string path); + /// + /// Read a static mapping file as text. + /// + /// The path (folder + filename with .json extension). + /// The file content as text. + string ReadMappingFile([NotNull] string path); - /// - /// Write the static mapping file. - /// - /// The path (folder + filename with .json extension). - /// The text. - void WriteMappingFile([NotNull] string path, [NotNull] string text); + /// + /// Write the static mapping file. + /// + /// The path (folder + filename with .json extension). + /// The text. + void WriteMappingFile([NotNull] string path, [NotNull] string text); - /// - /// Read a response body file as byte[]. - /// - /// The path or filename from the file to read. - /// The file content as bytes. - byte[] ReadResponseBodyAsFile([NotNull] string path); + /// + /// Read a response body file as byte[]. + /// + /// The path or filename from the file to read. + /// The file content as bytes. + byte[] ReadResponseBodyAsFile([NotNull] string path); - /// - /// Read a response body file as text. - /// - /// The path or filename from the file to read. - /// The file content as text. - string ReadResponseBodyAsString([NotNull] string path); + /// + /// Read a response body file as text. + /// + /// The path or filename from the file to read. + /// The file content as text. + string ReadResponseBodyAsString([NotNull] string path); - /// - /// Delete a file. - /// - /// The filename. - void DeleteFile([NotNull] string filename); + /// + /// Delete a file. + /// + /// The filename. + void DeleteFile([NotNull] string filename); - /// - /// Determines whether the given path refers to an existing file on disk. - /// - /// The filename. - /// true if path refers to an existing file; false if the file does not exist. - bool FileExists([NotNull] string filename); + /// + /// Determines whether the given path refers to an existing file on disk. + /// + /// The filename. + /// true if path refers to an existing file; false if the file does not exist. + bool FileExists([NotNull] string filename); - /// - /// Write a file. - /// - /// The filename. - /// The bytes. - void WriteFile([NotNull] string filename, [NotNull] byte[] bytes); + /// + /// Write a file. + /// + /// The filename. + /// The bytes. + void WriteFile([NotNull] string filename, [NotNull] byte[] bytes); - /// - /// Write a file. - /// - /// The folder. - /// The filename. - /// The bytes. - void WriteFile([NotNull] string folder, [NotNull] string filename, [NotNull] byte[] bytes); + /// + /// Write a file. + /// + /// The folder. + /// The filename. + /// The bytes. + void WriteFile([NotNull] string folder, [NotNull] string filename, [NotNull] byte[] bytes); - /// - /// Read a file as bytes. - /// - /// The filename. - /// The file content as bytes. - byte[] ReadFile([NotNull] string filename); + /// + /// Read a file as bytes. + /// + /// The filename. + /// The file content as bytes. + byte[] ReadFile([NotNull] string filename); - /// - /// Read a file as string. - /// - /// The filename. - /// The file content as a string. - string ReadFileAsString([NotNull] string filename); + /// + /// Read a file as string. + /// + /// The filename. + /// The file content as a string. + string ReadFileAsString([NotNull] string filename); - /// - /// Gets the folder where the unmatched requests should be stored. For local file system, this would be `{CurrentFolder}/requests/unmatched`. - /// - /// The folder name. - string GetUnmatchedRequestsFolder(); + /// + /// Gets the folder where the unmatched requests should be stored. For local file system, this would be `{CurrentFolder}/requests/unmatched`. + /// + /// The folder name. + string GetUnmatchedRequestsFolder(); - /// - /// Write a unmatched request to the Unmatched RequestsFolder. - /// - /// The filename. - /// The text. - void WriteUnmatchedRequest([NotNull] string filename, [NotNull] string text); - } + /// + /// Write a unmatched request to the Unmatched RequestsFolder. + /// + /// The filename. + /// The text. + void WriteUnmatchedRequest([NotNull] string filename, [NotNull] string text); } \ No newline at end of file diff --git a/src/WireMock.Net.Abstractions/Logging/IWireMockLogger.cs b/src/WireMock.Net.Abstractions/Logging/IWireMockLogger.cs index 0336295d..14a04736 100644 --- a/src/WireMock.Net.Abstractions/Logging/IWireMockLogger.cs +++ b/src/WireMock.Net.Abstractions/Logging/IWireMockLogger.cs @@ -2,65 +2,63 @@ using System; using JetBrains.Annotations; using WireMock.Admin.Requests; -namespace WireMock.Logging +namespace WireMock.Logging; + +/// +/// IWireMockLogger interface +/// +[PublicAPI] +public interface IWireMockLogger { /// - /// IWireMockLogger interface + /// Writes the message at the Debug level using the specified parameters. /// + /// The format string. + /// The arguments. [PublicAPI] - public interface IWireMockLogger - { - /// - /// Writes the message at the Debug level using the specified parameters. - /// - /// The format string. - /// The arguments. - [PublicAPI] - [StringFormatMethod("formatString")] - void Debug(string formatString, params object[] args); + [StringFormatMethod("formatString")] + void Debug(string formatString, params object[] args); - /// - /// Writes the message at the Info level using the specified parameters. - /// - /// The format string. - /// The arguments. - [PublicAPI] - [StringFormatMethod("formatString")] - void Info(string formatString, params object[] args); + /// + /// Writes the message at the Info level using the specified parameters. + /// + /// The format string. + /// The arguments. + [PublicAPI] + [StringFormatMethod("formatString")] + void Info(string formatString, params object[] args); - /// - /// Writes the message at the Warning level using the specified parameters. - /// - /// The format string. - /// The arguments. - [PublicAPI] - [StringFormatMethod("formatString")] - void Warn(string formatString, params object[] args); + /// + /// Writes the message at the Warning level using the specified parameters. + /// + /// The format string. + /// The arguments. + [PublicAPI] + [StringFormatMethod("formatString")] + void Warn(string formatString, params object[] args); - /// - /// Writes the message at the Error level using the specified parameters. - /// - /// The format string. - /// The arguments. - [PublicAPI] - [StringFormatMethod("formatString")] - void Error(string formatString, params object[] args); + /// + /// Writes the message at the Error level using the specified parameters. + /// + /// The format string. + /// The arguments. + [PublicAPI] + [StringFormatMethod("formatString")] + void Error(string formatString, params object[] args); - /// - /// Writes the message at the Error level using the specified exception. - /// - /// The format string. - /// The exception. - [PublicAPI] - [StringFormatMethod("formatString")] - void Error(string formatString, Exception exception); + /// + /// Writes the message at the Error level using the specified exception. + /// + /// The format string. + /// The exception. + [PublicAPI] + void Error(string formatString, Exception exception); - /// - /// Writes the LogEntryModel (LogRequestModel, LogResponseModel and more). - /// - /// The Request Log Model. - /// Defines if this request is an admin request. - [PublicAPI] - void DebugRequestResponse(LogEntryModel logEntryModel, bool isAdminRequest); - } + /// + /// Writes the LogEntryModel (LogRequestModel, LogResponseModel and more). + /// + /// The Request Log Model. + /// Defines if this request is an admin request. + [PublicAPI] + void DebugRequestResponse(LogEntryModel logEntryModel, bool isAdminRequest); } \ No newline at end of file diff --git a/src/WireMock.Net.Abstractions/Matchers/Request/IRequestMatchResult.cs b/src/WireMock.Net.Abstractions/Matchers/Request/IRequestMatchResult.cs index d32b9d4f..52aae7c3 100644 --- a/src/WireMock.Net.Abstractions/Matchers/Request/IRequestMatchResult.cs +++ b/src/WireMock.Net.Abstractions/Matchers/Request/IRequestMatchResult.cs @@ -1,56 +1,56 @@ using System; using System.Collections.Generic; -namespace WireMock.Matchers.Request +namespace WireMock.Matchers.Request; + +/// +/// IRequestMatchResult +/// +public interface IRequestMatchResult : IComparable { /// - /// IRequestMatchResult + /// Gets the match percentage. /// - public interface IRequestMatchResult : IComparable - { - /// - /// Gets the match percentage. - /// - /// - /// The match percentage. - /// - double AverageTotalScore { get; } + /// + /// The match percentage. + /// + double AverageTotalScore { get; } - /// - /// Gets or sets a value indicating whether this instance is perfect match. - /// - /// - /// true if this instance is perfect match; otherwise, false. - /// - bool IsPerfectMatch { get; } + /// + /// Gets or sets a value indicating whether this instance is perfect match. + /// + /// + /// true if this instance is perfect match; otherwise, false. + /// + bool IsPerfectMatch { get; } - /// - /// Gets the match details. - /// - IList MatchDetails { get; } + /// + /// Gets the match details. + /// + IList MatchDetails { get; } - /// - /// Gets or sets the total number of matches. - /// - /// - /// The total number of matches. - /// - int TotalNumber { get; } + /// + /// Gets or sets the total number of matches. + /// + /// + /// The total number of matches. + /// + int TotalNumber { get; } - /// - /// Gets or sets the match-score. - /// - /// - /// The match-score. - /// - double TotalScore { get; } + /// + /// Gets or sets the match-score. + /// + /// + /// The match-score. + /// + double TotalScore { get; } - /// - /// Adds the score. - /// - /// The matcher Type. - /// The score. - /// The score. - double AddScore(Type matcherType, double score); - } + /// + /// Adds the score. + /// + /// The matcher Type. + /// The score. + /// The exception [Optional]. + /// The score. + double AddScore(Type matcherType, double score, Exception? exception); } \ No newline at end of file diff --git a/src/WireMock.Net.Abstractions/Matchers/Request/MatchDetail.cs b/src/WireMock.Net.Abstractions/Matchers/Request/MatchDetail.cs index 31f987d7..006706e6 100644 --- a/src/WireMock.Net.Abstractions/Matchers/Request/MatchDetail.cs +++ b/src/WireMock.Net.Abstractions/Matchers/Request/MatchDetail.cs @@ -1,20 +1,25 @@ -using System; +using System; -namespace WireMock.Matchers.Request +namespace WireMock.Matchers.Request; + +/// +/// MatchDetail +/// +public class MatchDetail { /// - /// MatchDetail + /// Gets or sets the type of the matcher. /// - public class MatchDetail - { - /// - /// Gets or sets the type of the matcher. - /// - public Type MatcherType { get; set; } + public Type MatcherType { get; set; } = null!; - /// - /// Gets or sets the score between 0.0 and 1.0 - /// - public double Score { get; set; } - } + /// + /// Gets or sets the score between 0.0 and 1.0 + /// + public double Score { get; set; } + + /// + /// The exception in case the Matcher throws exception. + /// [Optional] + /// + public Exception? Exception { get; set; } } \ No newline at end of file diff --git a/src/WireMock.Net.Matchers.CSharpCode/Matchers/CSharpCodeMatcher.cs b/src/WireMock.Net.Matchers.CSharpCode/Matchers/CSharpCodeMatcher.cs index c8b8d0f2..ad1fec76 100644 --- a/src/WireMock.Net.Matchers.CSharpCode/Matchers/CSharpCodeMatcher.cs +++ b/src/WireMock.Net.Matchers.CSharpCode/Matchers/CSharpCodeMatcher.cs @@ -30,11 +30,9 @@ internal class CSharpCodeMatcher : ICSharpCodeMatcher "Newtonsoft.Json.Linq" }; + /// public MatchBehaviour MatchBehaviour { get; } - /// - public bool ThrowException { get; } - private readonly AnyOf[] _patterns; /// @@ -55,37 +53,44 @@ internal class CSharpCodeMatcher : ICSharpCodeMatcher { _patterns = Guard.NotNull(patterns); MatchBehaviour = matchBehaviour; - ThrowException = false; MatchOperator = matchOperator; } - public double IsMatch(string? input) + public MatchResult IsMatch(string? input) { return IsMatchInternal(input); } - public double IsMatch(object? input) + public MatchResult IsMatch(object? input) { return IsMatchInternal(input); } - public double IsMatchInternal(object? input) + public MatchResult IsMatchInternal(object? input) { - double match = MatchScores.Mismatch; + var score = MatchScores.Mismatch; + Exception? exception = null; if (input != null) { - match = MatchScores.ToScore(_patterns.Select(pattern => IsMatch(input, pattern.GetPattern())).ToArray(), MatchOperator); + try + { + score = MatchScores.ToScore(_patterns.Select(pattern => IsMatch(input, pattern.GetPattern())).ToArray(), MatchOperator); + } + catch (Exception ex) + { + exception = ex; + } } - return MatchBehaviourHelper.Convert(MatchBehaviour, match); + return new MatchResult(MatchBehaviourHelper.Convert(MatchBehaviour, score), exception); } private bool IsMatch(dynamic input, string pattern) { - bool isMatchWithString = input is string; + var isMatchWithString = input is string; var inputValue = isMatchWithString ? input : JObject.FromObject(input); - string source = GetSourceForIsMatchWithString(pattern, isMatchWithString); + var source = GetSourceForIsMatchWithString(pattern, isMatchWithString); object? result; @@ -155,7 +160,7 @@ internal class CSharpCodeMatcher : ICSharpCodeMatcher } #elif (NETSTANDARD2_0 || NETSTANDARD2_1 || NETCOREAPP3_1 || NET5_0 || NET6_0 || NET7_0) - Assembly assembly; + Assembly assembly; try { assembly = CSScriptLib.CSScript.Evaluator.CompileCode(source); @@ -198,10 +203,10 @@ internal class CSharpCodeMatcher : ICSharpCodeMatcher private string GetSourceForIsMatchWithString(string pattern, bool isMatchWithString) { - string template = isMatchWithString ? TemplateForIsMatchWithString : TemplateForIsMatchWithDynamic; + var template = isMatchWithString ? TemplateForIsMatchWithString : TemplateForIsMatchWithDynamic; var stringBuilder = new StringBuilder(); - foreach (string @using in _usings) + foreach (var @using in _usings) { stringBuilder.AppendLine($"using {@using};"); } @@ -211,7 +216,7 @@ internal class CSharpCodeMatcher : ICSharpCodeMatcher return stringBuilder.ToString(); } - /// + /// public AnyOf[] GetPatterns() { return _patterns; @@ -220,6 +225,6 @@ internal class CSharpCodeMatcher : ICSharpCodeMatcher /// public MatchOperator MatchOperator { get; } - /// - public string Name => "CSharpCodeMatcher"; + /// + public string Name => nameof(CSharpCodeMatcher); } \ No newline at end of file diff --git a/src/WireMock.Net/Authentication/AzureADAuthenticationMatcher.cs b/src/WireMock.Net/Authentication/AzureADAuthenticationMatcher.cs index e81b8250..74caa295 100644 --- a/src/WireMock.Net/Authentication/AzureADAuthenticationMatcher.cs +++ b/src/WireMock.Net/Authentication/AzureADAuthenticationMatcher.cs @@ -34,8 +34,6 @@ internal class AzureADAuthenticationMatcher : IStringMatcher public MatchBehaviour MatchBehaviour => MatchBehaviour.AcceptOnMatch; - public bool ThrowException => false; - public AnyOf[] GetPatterns() { return EmptyArray>.Value; @@ -43,7 +41,7 @@ internal class AzureADAuthenticationMatcher : IStringMatcher public MatchOperator MatchOperator { get; } = MatchOperator.Or; - public double IsMatch(string? input) + public MatchResult IsMatch(string? input) { if (string.IsNullOrEmpty(input)) { @@ -70,9 +68,9 @@ internal class AzureADAuthenticationMatcher : IStringMatcher return MatchScores.Perfect; } - catch + catch (Exception ex) { - return MatchScores.Mismatch; + return new MatchResult(MatchScores.Mismatch, ex); } } } diff --git a/src/WireMock.Net/Constants/WireMockConstants.cs b/src/WireMock.Net/Constants/WireMockConstants.cs index 2a03f6f9..f7589451 100644 --- a/src/WireMock.Net/Constants/WireMockConstants.cs +++ b/src/WireMock.Net/Constants/WireMockConstants.cs @@ -8,4 +8,6 @@ internal static class WireMockConstants public const string ContentTypeJson = "application/json"; public const string ContentTypeTextPlain = "text/plain"; + + public const string NoMatchingFound = "No matching mapping found"; } \ No newline at end of file diff --git a/src/WireMock.Net/Extensions/ExceptionExtensions.cs b/src/WireMock.Net/Extensions/ExceptionExtensions.cs new file mode 100644 index 00000000..e4752ebd --- /dev/null +++ b/src/WireMock.Net/Extensions/ExceptionExtensions.cs @@ -0,0 +1,16 @@ +using System; + +namespace WireMock.Extensions; + +internal static class ExceptionExtensions +{ + public static Exception? ToException(this Exception[] exceptions) + { + return exceptions.Length switch + { + 1 => exceptions[0], + > 1 => new AggregateException(exceptions), + _ => null + }; + } +} \ No newline at end of file diff --git a/src/WireMock.Net/Handlers/LocalFileSystemHandler.cs b/src/WireMock.Net/Handlers/LocalFileSystemHandler.cs index aaa888c3..09521cb5 100644 --- a/src/WireMock.Net/Handlers/LocalFileSystemHandler.cs +++ b/src/WireMock.Net/Handlers/LocalFileSystemHandler.cs @@ -82,7 +82,7 @@ public class LocalFileSystemHandler : IFileSystemHandler public virtual byte[] ReadResponseBodyAsFile(string path) { Guard.NotNullOrEmpty(path); - path = PathUtils.CleanPath(path); + path = PathUtils.CleanPath(path)!; // If the file exists at the given path relative to the MappingsFolder, then return that. // Else the path will just be as-is. return File.ReadAllBytes(File.Exists(PathUtils.Combine(GetMappingFolder(), path)) ? PathUtils.Combine(GetMappingFolder(), path) : path); @@ -92,7 +92,7 @@ public class LocalFileSystemHandler : IFileSystemHandler public virtual string ReadResponseBodyAsString(string path) { Guard.NotNullOrEmpty(path); - path = PathUtils.CleanPath(path); + path = PathUtils.CleanPath(path)!; // In case the path is a filename, the path will be adjusted to the MappingFolder. // Else the path will just be as-is. return File.ReadAllText(File.Exists(PathUtils.Combine(GetMappingFolder(), path)) ? PathUtils.Combine(GetMappingFolder(), path) : path); diff --git a/src/WireMock.Net/Mapping.cs b/src/WireMock.Net/Mapping.cs index b678780a..019c208b 100644 --- a/src/WireMock.Net/Mapping.cs +++ b/src/WireMock.Net/Mapping.cs @@ -139,13 +139,13 @@ public class Mapping : IMapping Probability = probability; } - /// + /// public Task<(IResponseMessage Message, IMapping? Mapping)> ProvideResponseAsync(IRequestMessage requestMessage) { return Provider.ProvideResponseAsync(this, requestMessage, Settings); } - /// + /// public IRequestMatchResult GetRequestMatchResult(IRequestMessage requestMessage, string? nextState) { var result = new RequestMatchResult(); diff --git a/src/WireMock.Net/Matchers/AbstractJsonPartialMatcher.cs b/src/WireMock.Net/Matchers/AbstractJsonPartialMatcher.cs index 0aed05a8..0555285a 100644 --- a/src/WireMock.Net/Matchers/AbstractJsonPartialMatcher.cs +++ b/src/WireMock.Net/Matchers/AbstractJsonPartialMatcher.cs @@ -20,10 +20,8 @@ public abstract class AbstractJsonPartialMatcher : JsonMatcher /// /// The string value to check for equality. /// Ignore the case from the PropertyName and PropertyValue (string only). - /// Throw an exception when the internal matching fails because of invalid input. /// Support Regex. - protected AbstractJsonPartialMatcher(string value, bool ignoreCase = false, bool throwException = false, bool regex = false) - : base(value, ignoreCase, throwException) + protected AbstractJsonPartialMatcher(string value, bool ignoreCase = false, bool regex = false) : base(value, ignoreCase) { Regex = regex; } @@ -33,10 +31,8 @@ public abstract class AbstractJsonPartialMatcher : JsonMatcher /// /// The object value to check for equality. /// Ignore the case from the PropertyName and PropertyValue (string only). - /// Throw an exception when the internal matching fails because of invalid input. /// Support Regex. - protected AbstractJsonPartialMatcher(object value, bool ignoreCase = false, bool throwException = false, bool regex = false) - : base(value, ignoreCase, throwException) + protected AbstractJsonPartialMatcher(object value, bool ignoreCase = false, bool regex = false) : base(value, ignoreCase) { Regex = regex; } @@ -47,10 +43,8 @@ public abstract class AbstractJsonPartialMatcher : JsonMatcher /// The match behaviour. /// The value to check for equality. /// Ignore the case from the PropertyName and PropertyValue (string only). - /// Throw an exception when the internal matching fails because of invalid input. /// Support Regex. - protected AbstractJsonPartialMatcher(MatchBehaviour matchBehaviour, object value, bool ignoreCase = false, bool throwException = false, bool regex = false) - : base(matchBehaviour, value, ignoreCase, throwException) + protected AbstractJsonPartialMatcher(MatchBehaviour matchBehaviour, object value, bool ignoreCase = false, bool regex = false) : base(matchBehaviour, value, ignoreCase) { Regex = regex; } @@ -66,7 +60,7 @@ public abstract class AbstractJsonPartialMatcher : JsonMatcher if (Regex && value.Type == JTokenType.String && input != null) { var valueAsString = value.ToString(); - + var (valid, result) = RegexUtils.MatchRegex(valueAsString, input.ToString()); if (valid) { @@ -75,10 +69,10 @@ public abstract class AbstractJsonPartialMatcher : JsonMatcher } if (input != null && - ((value.Type == JTokenType.Guid && input.Type == JTokenType.String) || - (value.Type == JTokenType.String && input.Type == JTokenType.Guid))) + ((value.Type == JTokenType.Guid && input.Type == JTokenType.String) || + (value.Type == JTokenType.String && input.Type == JTokenType.Guid))) { - return IsMatch(value.ToString(), input.ToString()); + return IsMatch(value.ToString(), input.ToString()); } if (input == null || value.Type != input.Type) diff --git a/src/WireMock.Net/Matchers/ContentTypeMatcher.cs b/src/WireMock.Net/Matchers/ContentTypeMatcher.cs index 91deb2b5..7aa7263a 100644 --- a/src/WireMock.Net/Matchers/ContentTypeMatcher.cs +++ b/src/WireMock.Net/Matchers/ContentTypeMatcher.cs @@ -46,15 +46,13 @@ public class ContentTypeMatcher : WildcardMatcher /// The match behaviour. /// The patterns. /// IgnoreCase (default false) - /// Throw an exception when the internal matching fails because of invalid input. - public ContentTypeMatcher(MatchBehaviour matchBehaviour, AnyOf[] patterns, bool ignoreCase = false, bool throwException = false) : - base(matchBehaviour, patterns, ignoreCase, throwException) + public ContentTypeMatcher(MatchBehaviour matchBehaviour, AnyOf[] patterns, bool ignoreCase = false) : base(matchBehaviour, patterns, ignoreCase) { _patterns = patterns; } - /// - public override double IsMatch(string? input) + /// + public override MatchResult IsMatch(string? input) { if (string.IsNullOrEmpty(input) || !MediaTypeHeaderValue.TryParse(input, out var contentType)) { @@ -64,12 +62,12 @@ public class ContentTypeMatcher : WildcardMatcher return base.IsMatch(contentType.MediaType); } - /// + /// public override AnyOf[] GetPatterns() { return _patterns; } - /// - public override string Name => "ContentTypeMatcher"; + /// + public override string Name => nameof(ContentTypeMatcher); } \ No newline at end of file diff --git a/src/WireMock.Net/Matchers/ExactMatcher.cs b/src/WireMock.Net/Matchers/ExactMatcher.cs index fecac7d2..4d67eed9 100644 --- a/src/WireMock.Net/Matchers/ExactMatcher.cs +++ b/src/WireMock.Net/Matchers/ExactMatcher.cs @@ -14,17 +14,14 @@ public class ExactMatcher : IStringMatcher, IIgnoreCaseMatcher { private readonly AnyOf[] _values; - /// + /// public MatchBehaviour MatchBehaviour { get; } - /// - public bool ThrowException { get; } - /// /// Initializes a new instance of the class. /// /// The values. - public ExactMatcher(params AnyOf[] values) : this(MatchBehaviour.AcceptOnMatch, false, false, MatchOperator.Or, values) + public ExactMatcher(params AnyOf[] values) : this(MatchBehaviour.AcceptOnMatch, false, MatchOperator.Or, values) { } @@ -33,7 +30,7 @@ public class ExactMatcher : IStringMatcher, IIgnoreCaseMatcher /// /// Ignore the case from the pattern(s). /// The values. - public ExactMatcher(bool ignoreCase, params AnyOf[] values) : this(MatchBehaviour.AcceptOnMatch, ignoreCase, false, MatchOperator.Or, values) + public ExactMatcher(bool ignoreCase, params AnyOf[] values) : this(MatchBehaviour.AcceptOnMatch, ignoreCase, MatchOperator.Or, values) { } @@ -42,36 +39,33 @@ public class ExactMatcher : IStringMatcher, IIgnoreCaseMatcher /// /// The match behaviour. /// Ignore the case from the pattern(s). - /// Throw an exception when the internal matching fails because of invalid input. /// The to use. (default = "Or") /// The values. public ExactMatcher( MatchBehaviour matchBehaviour, bool ignoreCase = false, - bool throwException = false, MatchOperator matchOperator = MatchOperator.Or, params AnyOf[] values) { _values = Guard.NotNull(values); MatchBehaviour = matchBehaviour; - ThrowException = throwException; IgnoreCase = ignoreCase; MatchOperator = matchOperator; } - /// - public double IsMatch(string? input) + /// + public MatchResult IsMatch(string? input) { Func equals = IgnoreCase ? pattern => string.Equals(pattern, input, StringComparison.OrdinalIgnoreCase) : pattern => pattern == input; - double score = MatchScores.ToScore(_values.Select(v => equals(v)).ToArray(), MatchOperator); - return MatchBehaviourHelper.Convert(MatchBehaviour, score); + var score = MatchScores.ToScore(_values.Select(v => equals(v)).ToArray(), MatchOperator); + return new MatchResult(MatchBehaviourHelper.Convert(MatchBehaviour, score)); } - /// + /// public AnyOf[] GetPatterns() { return _values; @@ -80,7 +74,7 @@ public class ExactMatcher : IStringMatcher, IIgnoreCaseMatcher /// public MatchOperator MatchOperator { get; } - /// + /// public string Name => "ExactMatcher"; /// diff --git a/src/WireMock.Net/Matchers/ExactObjectMatcher.cs b/src/WireMock.Net/Matchers/ExactObjectMatcher.cs index 8b4e3786..bc01e70e 100644 --- a/src/WireMock.Net/Matchers/ExactObjectMatcher.cs +++ b/src/WireMock.Net/Matchers/ExactObjectMatcher.cs @@ -19,12 +19,9 @@ public class ExactObjectMatcher : IObjectMatcher /// public byte[]? ValueAsBytes { get; } - /// + /// public MatchBehaviour MatchBehaviour { get; } - /// - public bool ThrowException { get; } - /// /// Initializes a new instance of the class. /// @@ -56,17 +53,15 @@ public class ExactObjectMatcher : IObjectMatcher /// Initializes a new instance of the class. /// /// The match behaviour. - /// Throw an exception when the internal matching fails because of invalid input. /// The value. - public ExactObjectMatcher(MatchBehaviour matchBehaviour, byte[] value, bool throwException = false) + public ExactObjectMatcher(MatchBehaviour matchBehaviour, byte[] value) { ValueAsBytes = Guard.NotNull(value); MatchBehaviour = matchBehaviour; - ThrowException = throwException; } - /// - public double IsMatch(object? input) + /// + public MatchResult IsMatch(object? input) { bool equals = false; if (ValueAsObject != null) @@ -81,6 +76,6 @@ public class ExactObjectMatcher : IObjectMatcher return MatchBehaviourHelper.Convert(MatchBehaviour, MatchScores.ToScore(equals)); } - /// + /// public string Name => "ExactObjectMatcher"; } \ No newline at end of file diff --git a/src/WireMock.Net/Matchers/GraphQLMatcher.cs b/src/WireMock.Net/Matchers/GraphQLMatcher.cs index 02b3b58f..cb66c628 100644 --- a/src/WireMock.Net/Matchers/GraphQLMatcher.cs +++ b/src/WireMock.Net/Matchers/GraphQLMatcher.cs @@ -1,12 +1,14 @@ #if GRAPHQL using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using AnyOfTypes; using GraphQL; using GraphQL.Types; using Newtonsoft.Json; using Stef.Validation; +using WireMock.Extensions; using WireMock.Models; namespace WireMock.Matchers; @@ -19,8 +21,10 @@ public class GraphQLMatcher : IStringMatcher { private sealed class GraphQLRequest { + // ReSharper disable once UnusedAutoPropertyAccessor.Local public string? Query { get; set; } + // ReSharper disable once UnusedAutoPropertyAccessor.Local public Dictionary? Variables { get; set; } } @@ -31,21 +35,16 @@ public class GraphQLMatcher : IStringMatcher /// public MatchBehaviour MatchBehaviour { get; } - /// - public bool ThrowException { get; } - /// /// Initializes a new instance of the class. /// /// The schema. /// The match behaviour. - /// Throw an exception when the internal matching fails because of invalid input. /// The to use. (default = "Or") - public GraphQLMatcher(AnyOf schema, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch, bool throwException = false, MatchOperator matchOperator = MatchOperator.Or) + public GraphQLMatcher(AnyOf schema, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch, MatchOperator matchOperator = MatchOperator.Or) { Guard.NotNull(schema); MatchBehaviour = matchBehaviour; - ThrowException = throwException; MatchOperator = matchOperator; var patterns = new List>(); @@ -72,51 +71,44 @@ public class GraphQLMatcher : IStringMatcher } /// - public double IsMatch(string? input) + public MatchResult IsMatch(string? input) { - var match = MatchScores.Mismatch; + var score = MatchScores.Mismatch; + Exception? exception = null; - try + if (input != null && TryGetGraphQLRequest(input, out var graphQLRequest)) { - var graphQLRequest = JsonConvert.DeserializeObject(input!)!; - - var executionResult = new DocumentExecuter().ExecuteAsync(_ => + try { - _.ThrowOnUnhandledException = true; - - _.Schema = _schema; - _.Query = graphQLRequest.Query; - - if (graphQLRequest.Variables != null) + var executionResult = new DocumentExecuter().ExecuteAsync(_ => { - _.Variables = new Inputs(graphQLRequest.Variables); - } - }).GetAwaiter().GetResult(); + _.ThrowOnUnhandledException = true; - if (executionResult.Errors == null || executionResult.Errors.Count == 0) - { - match = MatchScores.Perfect; - } - else - { - var exceptions = executionResult.Errors.OfType().ToArray(); - if (exceptions.Length == 1) + _.Schema = _schema; + _.Query = graphQLRequest.Query; + + if (graphQLRequest.Variables != null) + { + _.Variables = new Inputs(graphQLRequest.Variables); + } + }).GetAwaiter().GetResult(); + + if (executionResult.Errors == null || executionResult.Errors.Count == 0) { - throw exceptions[0]; + score = MatchScores.Perfect; + } + else + { + exception = executionResult.Errors.OfType().ToArray().ToException(); } - - throw new AggregateException(exceptions); } - } - catch - { - if (ThrowException) + catch (Exception ex) { - throw; + exception = ex; } } - return MatchBehaviourHelper.Convert(MatchBehaviour, match); + return new MatchResult(MatchBehaviourHelper.Convert(MatchBehaviour, score), exception); } /// @@ -131,6 +123,20 @@ public class GraphQLMatcher : IStringMatcher /// public string Name => nameof(GraphQLMatcher); + private static bool TryGetGraphQLRequest(string input, [NotNullWhen(true)] out GraphQLRequest? graphQLRequest) + { + try + { + graphQLRequest = JsonConvert.DeserializeObject(input); + return graphQLRequest != null; + } + catch + { + graphQLRequest = default; + return false; + } + } + private static ISchema BuildSchema(string schema) { return Schema.For(schema); diff --git a/src/WireMock.Net/Matchers/Helpers/BodyDataMatchScoreCalculator.cs b/src/WireMock.Net/Matchers/Helpers/BodyDataMatchScoreCalculator.cs index 2050285a..57565c46 100644 --- a/src/WireMock.Net/Matchers/Helpers/BodyDataMatchScoreCalculator.cs +++ b/src/WireMock.Net/Matchers/Helpers/BodyDataMatchScoreCalculator.cs @@ -6,7 +6,7 @@ namespace WireMock.Matchers.Helpers; internal static class BodyDataMatchScoreCalculator { - public static double CalculateMatchScore(IBodyData? requestMessage, IMatcher matcher) + public static MatchResult CalculateMatchScore(IBodyData? requestMessage, IMatcher matcher) { Guard.NotNull(matcher); @@ -23,7 +23,7 @@ internal static class BodyDataMatchScoreCalculator return notNullOrEmptyMatcher.IsMatch(requestMessage.BodyAsBytes); default: - return MatchScores.Mismatch; + return default; } } @@ -63,16 +63,6 @@ internal static class BodyDataMatchScoreCalculator } } -#if MIMEKIT_XXX - if (matcher is MultiPartMatcher multiPartMatcher) - { - // If the body is a String or MultiPart, use the BodyAsString to match on. - if (requestMessage?.DetectedBodyType is BodyType.String or BodyType.MultiPart) - { - return multiPartMatcher.IsMatch(requestMessage.BodyAsString); - } - } -#endif - return MatchScores.Mismatch; + return default; } } \ No newline at end of file diff --git a/src/WireMock.Net/Matchers/IMatcher.cs b/src/WireMock.Net/Matchers/IMatcher.cs index 5da3a6d7..a0741028 100644 --- a/src/WireMock.Net/Matchers/IMatcher.cs +++ b/src/WireMock.Net/Matchers/IMatcher.cs @@ -14,9 +14,4 @@ public interface IMatcher /// Gets the match behaviour. /// MatchBehaviour MatchBehaviour { get; } - - /// - /// Should this matcher throw an exception? - /// - bool ThrowException { get; } } \ No newline at end of file diff --git a/src/WireMock.Net/Matchers/IObjectMatcher.cs b/src/WireMock.Net/Matchers/IObjectMatcher.cs index 8957b65d..439a469b 100644 --- a/src/WireMock.Net/Matchers/IObjectMatcher.cs +++ b/src/WireMock.Net/Matchers/IObjectMatcher.cs @@ -9,6 +9,6 @@ public interface IObjectMatcher : IMatcher /// Determines whether the specified input is match. /// /// The input. - /// A value between 0.0 - 1.0 of the similarity. - double IsMatch(object? input); + /// MatchResult + MatchResult IsMatch(object? input); } \ No newline at end of file diff --git a/src/WireMock.Net/Matchers/IStringMatcher.cs b/src/WireMock.Net/Matchers/IStringMatcher.cs index bf815eee..f405b198 100644 --- a/src/WireMock.Net/Matchers/IStringMatcher.cs +++ b/src/WireMock.Net/Matchers/IStringMatcher.cs @@ -13,8 +13,8 @@ public interface IStringMatcher : IMatcher /// Determines whether the specified input is match. /// /// The input. - /// A value between 0.0 - 1.0 of the similarity. - double IsMatch(string? input); + /// MatchResult + MatchResult IsMatch(string? input); /// /// Gets the patterns. diff --git a/src/WireMock.Net/Matchers/JSONPathMatcher.cs b/src/WireMock.Net/Matchers/JSONPathMatcher.cs index 5437a75f..4cc3ec9e 100644 --- a/src/WireMock.Net/Matchers/JSONPathMatcher.cs +++ b/src/WireMock.Net/Matchers/JSONPathMatcher.cs @@ -1,6 +1,6 @@ +using System; using System.Linq; using AnyOfTypes; -using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Stef.Validation; using WireMock.Extensions; @@ -17,17 +17,15 @@ public class JsonPathMatcher : IStringMatcher, IObjectMatcher { private readonly AnyOf[] _patterns; - /// + /// public MatchBehaviour MatchBehaviour { get; } - /// - public bool ThrowException { get; } - /// /// Initializes a new instance of the class. /// /// The patterns. - public JsonPathMatcher(params string[] patterns) : this(MatchBehaviour.AcceptOnMatch, false, MatchOperator.Or, patterns.ToAnyOfPatterns()) + public JsonPathMatcher(params string[] patterns) : this(MatchBehaviour.AcceptOnMatch, MatchOperator.Or, + patterns.ToAnyOfPatterns()) { } @@ -35,7 +33,8 @@ public class JsonPathMatcher : IStringMatcher, IObjectMatcher /// Initializes a new instance of the class. /// /// The patterns. - public JsonPathMatcher(params AnyOf[] patterns) : this(MatchBehaviour.AcceptOnMatch, false, MatchOperator.Or, patterns) + public JsonPathMatcher(params AnyOf[] patterns) : this(MatchBehaviour.AcceptOnMatch, + MatchOperator.Or, patterns) { } @@ -43,48 +42,45 @@ public class JsonPathMatcher : IStringMatcher, IObjectMatcher /// Initializes a new instance of the class. /// /// The match behaviour. - /// Throw an exception when the internal matching fails because of invalid input. /// The to use. (default = "Or") /// The patterns. public JsonPathMatcher( MatchBehaviour matchBehaviour, - bool throwException = false, MatchOperator matchOperator = MatchOperator.Or, params AnyOf[] patterns) { _patterns = Guard.NotNull(patterns); MatchBehaviour = matchBehaviour; - ThrowException = throwException; MatchOperator = matchOperator; } - /// - public double IsMatch(string? input) + /// + public MatchResult IsMatch(string? input) { - double match = MatchScores.Mismatch; + var score = MatchScores.Mismatch; + Exception? exception = null; + if (input != null) { try { var jToken = JToken.Parse(input); - match = IsMatch(jToken); + score = IsMatch(jToken); } - catch (JsonException) + catch (Exception ex) { - if (ThrowException) - { - throw; - } + exception = ex; } } - return MatchBehaviourHelper.Convert(MatchBehaviour, match); + return new MatchResult(MatchBehaviourHelper.Convert(MatchBehaviour, score), exception); } - /// - public double IsMatch(object? input) + /// + public MatchResult IsMatch(object? input) { - double match = MatchScores.Mismatch; + var score = MatchScores.Mismatch; + Exception? exception = null; // When input is null or byte[], return Mismatch. if (input != null && !(input is byte[])) @@ -93,18 +89,15 @@ public class JsonPathMatcher : IStringMatcher, IObjectMatcher { // Check if JToken or object JToken jToken = input as JToken ?? JObject.FromObject(input); - match = IsMatch(jToken); + score = IsMatch(jToken); } - catch (JsonException) + catch (Exception ex) { - if (ThrowException) - { - throw; - } + exception = ex; } } - return MatchBehaviourHelper.Convert(MatchBehaviour, match); + return new MatchResult(MatchBehaviourHelper.Convert(MatchBehaviour, score), exception); } /// @@ -116,7 +109,7 @@ public class JsonPathMatcher : IStringMatcher, IObjectMatcher /// public MatchOperator MatchOperator { get; } - /// + /// public string Name => "JsonPathMatcher"; private double IsMatch(JToken jToken) @@ -125,7 +118,8 @@ public class JsonPathMatcher : IStringMatcher, IObjectMatcher // The SelectToken method can accept a string path to a child token ( i.e. "Manufacturers[0].Products[0].Price"). // In that case it will return a JValue (some type) which does not implement the IEnumerable interface. - return MatchScores.ToScore(_patterns.Select(pattern => array.SelectToken(pattern.GetPattern()) != null).ToArray(), MatchOperator); + return MatchScores.ToScore( + _patterns.Select(pattern => array.SelectToken(pattern.GetPattern()) != null).ToArray(), MatchOperator); } // https://github.com/WireMock-Net/WireMock.Net/issues/965 @@ -151,4 +145,4 @@ public class JsonPathMatcher : IStringMatcher, IObjectMatcher return jToken; } -} +} \ No newline at end of file diff --git a/src/WireMock.Net/Matchers/JmesPathMatcher.cs b/src/WireMock.Net/Matchers/JmesPathMatcher.cs index 511c770b..0f1488cd 100644 --- a/src/WireMock.Net/Matchers/JmesPathMatcher.cs +++ b/src/WireMock.Net/Matchers/JmesPathMatcher.cs @@ -1,3 +1,4 @@ +using System; using System.Linq; using AnyOfTypes; using DevLab.JmesPath; @@ -15,17 +16,14 @@ public class JmesPathMatcher : IStringMatcher, IObjectMatcher { private readonly AnyOf[] _patterns; - /// + /// public MatchBehaviour MatchBehaviour { get; } - /// - public bool ThrowException { get; } - /// /// Initializes a new instance of the class. /// /// The patterns. - public JmesPathMatcher(params string[] patterns) : this(MatchBehaviour.AcceptOnMatch, false, MatchOperator.Or, patterns.ToAnyOfPatterns()) + public JmesPathMatcher(params string[] patterns) : this(MatchBehaviour.AcceptOnMatch, MatchOperator.Or, patterns.ToAnyOfPatterns()) { } @@ -33,18 +31,17 @@ public class JmesPathMatcher : IStringMatcher, IObjectMatcher /// Initializes a new instance of the class. /// /// The patterns. - public JmesPathMatcher(params AnyOf[] patterns) : this(MatchBehaviour.AcceptOnMatch, false, MatchOperator.Or, patterns) + public JmesPathMatcher(params AnyOf[] patterns) : this(MatchBehaviour.AcceptOnMatch, MatchOperator.Or, patterns) { } /// /// Initializes a new instance of the class. /// - /// Throw an exception when the internal matching fails because of invalid input. /// The to use. /// The patterns. - public JmesPathMatcher(bool throwException = false, MatchOperator matchOperator = MatchOperator.Or, params AnyOf[] patterns) : - this(MatchBehaviour.AcceptOnMatch, throwException, matchOperator, patterns) + public JmesPathMatcher(MatchOperator matchOperator = MatchOperator.Or, params AnyOf[] patterns) : + this(MatchBehaviour.AcceptOnMatch, matchOperator, patterns) { } @@ -52,60 +49,56 @@ public class JmesPathMatcher : IStringMatcher, IObjectMatcher /// Initializes a new instance of the class. /// /// The match behaviour. - /// Throw an exception when the internal matching fails because of invalid input. /// The to use. /// The patterns. public JmesPathMatcher( MatchBehaviour matchBehaviour, - bool throwException = false, MatchOperator matchOperator = MatchOperator.Or, params AnyOf[] patterns) { _patterns = Guard.NotNull(patterns); MatchBehaviour = matchBehaviour; - ThrowException = throwException; MatchOperator = matchOperator; } - /// - public double IsMatch(string? input) + /// + public MatchResult IsMatch(string? input) { - double match = MatchScores.Mismatch; + var score = MatchScores.Mismatch; + Exception? exception = null; + if (input != null) { try { var results = _patterns.Select(pattern => bool.Parse(new JmesPath().Transform(input, pattern.GetPattern()))).ToArray(); - match = MatchScores.ToScore(results, MatchOperator); + score = MatchScores.ToScore(results, MatchOperator); } - catch (JsonException) + catch (Exception ex) { - if (ThrowException) - { - throw; - } + exception = ex; } } - return MatchBehaviourHelper.Convert(MatchBehaviour, match); + return new MatchResult(MatchBehaviourHelper.Convert(MatchBehaviour, score), exception); } - /// - public double IsMatch(object? input) + /// + public MatchResult IsMatch(object? input) { - double match = MatchScores.Mismatch; + var score = MatchScores.Mismatch; // When input is null or byte[], return Mismatch. if (input != null && !(input is byte[])) { - string inputAsString = JsonConvert.SerializeObject(input); + var inputAsString = JsonConvert.SerializeObject(input); return IsMatch(inputAsString); } - return MatchBehaviourHelper.Convert(MatchBehaviour, match); + return MatchBehaviourHelper.Convert(MatchBehaviour, score); } - /// + /// public AnyOf[] GetPatterns() { return _patterns; @@ -114,6 +107,6 @@ public class JmesPathMatcher : IStringMatcher, IObjectMatcher /// public MatchOperator MatchOperator { get; } - /// - public string Name => "JmesPathMatcher"; + /// + public string Name => nameof(JmesPathMatcher); } \ No newline at end of file diff --git a/src/WireMock.Net/Matchers/JsonMatcher.cs b/src/WireMock.Net/Matchers/JsonMatcher.cs index 1f8398cc..29602318 100644 --- a/src/WireMock.Net/Matchers/JsonMatcher.cs +++ b/src/WireMock.Net/Matchers/JsonMatcher.cs @@ -1,7 +1,6 @@ using System; using System.Collections; using System.Linq; -using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Stef.Validation; using WireMock.Util; @@ -13,21 +12,18 @@ namespace WireMock.Matchers; /// public class JsonMatcher : IValueMatcher, IIgnoreCaseMatcher { - /// + /// public virtual string Name => "JsonMatcher"; /// public object Value { get; } - - /// + + /// public MatchBehaviour MatchBehaviour { get; } /// public bool IgnoreCase { get; } - /// - public bool ThrowException { get; } - private readonly JToken _valueAsJToken; private readonly Func _jTokenConverter; @@ -36,8 +32,7 @@ public class JsonMatcher : IValueMatcher, IIgnoreCaseMatcher /// /// The string value to check for equality. /// Ignore the case from the PropertyName and PropertyValue (string only). - /// Throw an exception when the internal matching fails because of invalid input. - public JsonMatcher(string value, bool ignoreCase = false, bool throwException = false) : this(MatchBehaviour.AcceptOnMatch, value, ignoreCase, throwException) + public JsonMatcher(string value, bool ignoreCase = false) : this(MatchBehaviour.AcceptOnMatch, value, ignoreCase) { } @@ -46,8 +41,7 @@ public class JsonMatcher : IValueMatcher, IIgnoreCaseMatcher /// /// The object value to check for equality. /// Ignore the case from the PropertyName and PropertyValue (string only). - /// Throw an exception when the internal matching fails because of invalid input. - public JsonMatcher(object value, bool ignoreCase = false, bool throwException = false) : this(MatchBehaviour.AcceptOnMatch, value, ignoreCase, throwException) + public JsonMatcher(object value, bool ignoreCase = false) : this(MatchBehaviour.AcceptOnMatch, value, ignoreCase) { } @@ -57,24 +51,23 @@ public class JsonMatcher : IValueMatcher, IIgnoreCaseMatcher /// The match behaviour. /// The value to check for equality. /// Ignore the case from the PropertyName and PropertyValue (string only). - /// Throw an exception when the internal matching fails because of invalid input. - public JsonMatcher(MatchBehaviour matchBehaviour, object value, bool ignoreCase = false, bool throwException = false) + public JsonMatcher(MatchBehaviour matchBehaviour, object value, bool ignoreCase = false) { Guard.NotNull(value, nameof(value)); MatchBehaviour = matchBehaviour; IgnoreCase = ignoreCase; - ThrowException = throwException; Value = value; _valueAsJToken = ConvertValueToJToken(value); _jTokenConverter = ignoreCase ? Rename : jToken => jToken; } - /// - public double IsMatch(object? input) + /// + public MatchResult IsMatch(object? input) { - bool match = false; + var score = MatchScores.Mismatch; + Exception? error = null; // When input is null or byte[], return Mismatch. if (input != null && input is not byte[]) @@ -83,20 +76,16 @@ public class JsonMatcher : IValueMatcher, IIgnoreCaseMatcher { var inputAsJToken = ConvertValueToJToken(input); - match = IsMatch( - _jTokenConverter(_valueAsJToken), - _jTokenConverter(inputAsJToken)); + var match = IsMatch(_jTokenConverter(_valueAsJToken), _jTokenConverter(inputAsJToken)); + score = MatchScores.ToScore(match); } - catch (JsonException) + catch (Exception ex) { - if (ThrowException) - { - throw; - } + error = ex; } } - return MatchBehaviourHelper.Convert(MatchBehaviour, MatchScores.ToScore(match)); + return new MatchResult(MatchBehaviourHelper.Convert(MatchBehaviour, score), error); } /// diff --git a/src/WireMock.Net/Matchers/JsonPartialMatcher.cs b/src/WireMock.Net/Matchers/JsonPartialMatcher.cs index 5ba99518..eb0afe9c 100644 --- a/src/WireMock.Net/Matchers/JsonPartialMatcher.cs +++ b/src/WireMock.Net/Matchers/JsonPartialMatcher.cs @@ -9,27 +9,27 @@ public class JsonPartialMatcher : AbstractJsonPartialMatcher public override string Name => nameof(JsonPartialMatcher); /// - public JsonPartialMatcher(string value, bool ignoreCase = false, bool throwException = false, bool regex = false) - : base(value, ignoreCase, throwException, regex) + public JsonPartialMatcher(string value, bool ignoreCase = false, bool regex = false) + : base(value, ignoreCase, regex) { } /// - public JsonPartialMatcher(object value, bool ignoreCase = false, bool throwException = false, bool regex = false) - : base(value, ignoreCase, throwException, regex) + public JsonPartialMatcher(object value, bool ignoreCase = false, bool regex = false) + : base(value, ignoreCase, regex) { } /// - public JsonPartialMatcher(MatchBehaviour matchBehaviour, object value, bool ignoreCase = false, bool throwException = false, bool regex = false) - : base(matchBehaviour, value, ignoreCase, throwException, regex) + public JsonPartialMatcher(MatchBehaviour matchBehaviour, object value, bool ignoreCase = false, bool regex = false) + : base(matchBehaviour, value, ignoreCase, regex) { } /// protected override bool IsMatch(string value, string input) { - var exactStringMatcher = new ExactMatcher(MatchBehaviour.AcceptOnMatch, IgnoreCase, ThrowException, MatchOperator.Or, value); - return MatchScores.IsPerfect(exactStringMatcher.IsMatch(input)); + var exactStringMatcher = new ExactMatcher(MatchBehaviour.AcceptOnMatch, IgnoreCase, MatchOperator.Or, value); + return exactStringMatcher.IsMatch(input).IsPerfect(); } } \ No newline at end of file diff --git a/src/WireMock.Net/Matchers/JsonPartialWildCardMatcher.cs b/src/WireMock.Net/Matchers/JsonPartialWildCardMatcher.cs index 7ca88807..09f777e8 100644 --- a/src/WireMock.Net/Matchers/JsonPartialWildCardMatcher.cs +++ b/src/WireMock.Net/Matchers/JsonPartialWildCardMatcher.cs @@ -9,20 +9,20 @@ public class JsonPartialWildcardMatcher : AbstractJsonPartialMatcher public override string Name => nameof(JsonPartialWildcardMatcher); /// - public JsonPartialWildcardMatcher(string value, bool ignoreCase = false, bool throwException = false, bool regex = false) - : base(value, ignoreCase, throwException, regex) + public JsonPartialWildcardMatcher(string value, bool ignoreCase = false, bool regex = false) + : base(value, ignoreCase, regex) { } /// - public JsonPartialWildcardMatcher(object value, bool ignoreCase = false, bool throwException = false, bool regex = false) - : base(value, ignoreCase, throwException, regex) + public JsonPartialWildcardMatcher(object value, bool ignoreCase = false, bool regex = false) + : base(value, ignoreCase, regex) { } /// - public JsonPartialWildcardMatcher(MatchBehaviour matchBehaviour, object value, bool ignoreCase = false, bool throwException = false, bool regex = false) - : base(matchBehaviour, value, ignoreCase, throwException, regex) + public JsonPartialWildcardMatcher(MatchBehaviour matchBehaviour, object value, bool ignoreCase = false, bool regex = false) + : base(matchBehaviour, value, ignoreCase, regex) { } @@ -30,6 +30,6 @@ public class JsonPartialWildcardMatcher : AbstractJsonPartialMatcher protected override bool IsMatch(string value, string input) { var wildcardStringMatcher = new WildcardMatcher(MatchBehaviour.AcceptOnMatch, value, IgnoreCase); - return MatchScores.IsPerfect(wildcardStringMatcher.IsMatch(input)); + return wildcardStringMatcher.IsMatch(input).IsPerfect(); } } \ No newline at end of file diff --git a/src/WireMock.Net/Matchers/LinqMatcher.cs b/src/WireMock.Net/Matchers/LinqMatcher.cs index 48f17dbc..8c6b9228 100644 --- a/src/WireMock.Net/Matchers/LinqMatcher.cs +++ b/src/WireMock.Net/Matchers/LinqMatcher.cs @@ -1,3 +1,4 @@ +using System; using System.Linq; using System.Linq.Dynamic.Core; using AnyOfTypes; @@ -18,12 +19,9 @@ public class LinqMatcher : IObjectMatcher, IStringMatcher { private readonly AnyOf[] _patterns; - /// + /// public MatchBehaviour MatchBehaviour { get; } - /// - public bool ThrowException { get; } - /// /// Initializes a new instance of the class. /// @@ -36,7 +34,7 @@ public class LinqMatcher : IObjectMatcher, IStringMatcher /// Initializes a new instance of the class. /// /// The patterns. - public LinqMatcher(params AnyOf[] patterns) : this(MatchBehaviour.AcceptOnMatch, false, MatchOperator.Or, patterns) + public LinqMatcher(params AnyOf[] patterns) : this(MatchBehaviour.AcceptOnMatch, MatchOperator.Or, patterns) { } @@ -45,7 +43,7 @@ public class LinqMatcher : IObjectMatcher, IStringMatcher /// /// The match behaviour. /// The pattern. - public LinqMatcher(MatchBehaviour matchBehaviour, AnyOf pattern) : this(matchBehaviour, false, MatchOperator.Or, pattern) + public LinqMatcher(MatchBehaviour matchBehaviour, AnyOf pattern) : this(matchBehaviour, MatchOperator.Or, pattern) { } @@ -53,25 +51,23 @@ public class LinqMatcher : IObjectMatcher, IStringMatcher /// Initializes a new instance of the class. /// /// The match behaviour. - /// Throw an exception when the internal matching fails because of invalid input. /// The to use. (default = "Or") /// The patterns. public LinqMatcher( MatchBehaviour matchBehaviour, - bool throwException = false, MatchOperator matchOperator = MatchOperator.Or, params AnyOf[] patterns) { _patterns = Guard.NotNull(patterns); MatchBehaviour = matchBehaviour; - ThrowException = throwException; MatchOperator = matchOperator; } /// - public double IsMatch(string? input) + public MatchResult IsMatch(string? input) { - double match = MatchScores.Mismatch; + var score = MatchScores.Mismatch; + Exception? error = null; // Convert a single input string to a Queryable string-list with 1 entry. IQueryable queryable = new[] { input }.AsQueryable(); @@ -79,25 +75,21 @@ public class LinqMatcher : IObjectMatcher, IStringMatcher try { // Use the Any(...) method to check if the result matches - match = MatchScores.ToScore(_patterns.Select(pattern => queryable.Any(pattern.GetPattern())).ToArray(), MatchOperator); - - return MatchBehaviourHelper.Convert(MatchBehaviour, match); + score = MatchScores.ToScore(_patterns.Select(pattern => queryable.Any(pattern.GetPattern())).ToArray(), MatchOperator); } - catch + catch (Exception e) { - if (ThrowException) - { - throw; - } + error = e; } - return MatchBehaviourHelper.Convert(MatchBehaviour, match); + return new MatchResult(MatchBehaviourHelper.Convert(MatchBehaviour, score), error); } /// - public double IsMatch(object? input) + public MatchResult IsMatch(object? input) { - double match = MatchScores.Mismatch; + var score = MatchScores.Mismatch; + Exception? error = null; JArray jArray; try @@ -106,7 +98,7 @@ public class LinqMatcher : IObjectMatcher, IStringMatcher } catch { - jArray = new JArray { JToken.FromObject(input) }; + jArray = input == null ? new JArray() : new JArray { JToken.FromObject(input) }; } // Convert a single object to a Queryable JObject-list with 1 entry. @@ -117,19 +109,14 @@ public class LinqMatcher : IObjectMatcher, IStringMatcher var patternsAsStringArray = _patterns.Select(p => p.GetPattern()).ToArray(); var scores = patternsAsStringArray.Select(p => queryable.Any(p)).ToArray(); - match = MatchScores.ToScore(scores, MatchOperator); - - return MatchBehaviourHelper.Convert(MatchBehaviour, match); + score = MatchScores.ToScore(scores, MatchOperator); } - catch + catch (Exception e) { - if (ThrowException) - { - throw; - } + error = e; } - return MatchBehaviourHelper.Convert(MatchBehaviour, match); + return new MatchResult(MatchBehaviourHelper.Convert(MatchBehaviour, score), error); } /// @@ -142,5 +129,5 @@ public class LinqMatcher : IObjectMatcher, IStringMatcher public MatchOperator MatchOperator { get; } /// - public string Name => "LinqMatcher"; + public string Name => nameof(LinqMatcher); } \ No newline at end of file diff --git a/src/WireMock.Net/Matchers/MatchResult.cs b/src/WireMock.Net/Matchers/MatchResult.cs new file mode 100644 index 00000000..a350d7d7 --- /dev/null +++ b/src/WireMock.Net/Matchers/MatchResult.cs @@ -0,0 +1,89 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Stef.Validation; +using WireMock.Extensions; + +namespace WireMock.Matchers; + +/// +/// The MatchResult which contains the score (value between 0.0 - 1.0 of the similarity) and an optional error message. +/// +public struct MatchResult +{ + /// + /// A value between 0.0 - 1.0 of the similarity. + /// + public double Score { get; set; } + + /// + /// The exception message) in case the matching fails. + /// [Optional] + /// + public Exception? Exception { get; set; } + + /// + /// Create a MatchResult + /// + /// A value between 0.0 - 1.0 of the similarity. + /// The exception in case the matching fails. [Optional] + public MatchResult(double score, Exception? exception = null) + { + Score = score; + Exception = exception; + } + + /// + /// Create a MatchResult + /// + /// The exception in case the matching fails. + public MatchResult(Exception exception) + { + Exception = Guard.NotNull(exception); + } + + /// + /// Implicitly converts a double to a MatchResult. + /// + /// The score + public static implicit operator MatchResult(double score) + { + return new MatchResult(score); + } + + /// + /// Is the value a perfect match? + /// + public bool IsPerfect() => MatchScores.IsPerfect(Score); + + /// + /// Create a MatchResult from multiple MatchResults. + /// + /// A list of MatchResults. + /// The MatchOperator + /// MatchResult + public static MatchResult From(IReadOnlyList matchResults, MatchOperator matchOperator) + { + Guard.NotNullOrEmpty(matchResults); + + if (matchResults.Count == 1) + { + return matchResults[0]; + } + + return new MatchResult + { + Score = MatchScores.ToScore(matchResults.Select(r => r.Score).ToArray(), matchOperator), + Exception = matchResults.Select(m => m.Exception).OfType().ToArray().ToException() + }; + } + + /// + /// Expand to Tuple + /// + /// Tuple : Score and Exception + public (double Score, Exception? Exception) Expand() + { + return (Score, Exception); + } +} \ No newline at end of file diff --git a/src/WireMock.Net/Matchers/MimePartMatcher.cs b/src/WireMock.Net/Matchers/MimePartMatcher.cs index 410efd7a..14505282 100644 --- a/src/WireMock.Net/Matchers/MimePartMatcher.cs +++ b/src/WireMock.Net/Matchers/MimePartMatcher.cs @@ -1,7 +1,9 @@ #if MIMEKIT using System; using MimeKit; +using WireMock.Matchers; using WireMock.Matchers.Helpers; +using WireMock.Models; using WireMock.Util; namespace WireMock.Matchers; @@ -11,7 +13,7 @@ namespace WireMock.Matchers; /// public class MimePartMatcher : IMatcher { - private readonly Func[] _funcs; + private readonly Func[] _funcs; /// public string Name => nameof(MimePartMatcher); @@ -39,9 +41,6 @@ public class MimePartMatcher : IMatcher /// public MatchBehaviour MatchBehaviour { get; } - /// - public bool ThrowException { get; } - /// /// Initializes a new instance of the class. /// @@ -50,8 +49,7 @@ public class MimePartMatcher : IMatcher IStringMatcher? contentTypeMatcher, IStringMatcher? contentDispositionMatcher, IStringMatcher? contentTransferEncodingMatcher, - IMatcher? contentMatcher, - bool throwException = false + IMatcher? contentMatcher ) { MatchBehaviour = matchBehaviour; @@ -59,7 +57,6 @@ public class MimePartMatcher : IMatcher ContentDispositionMatcher = contentDispositionMatcher; ContentTransferEncodingMatcher = contentTransferEncodingMatcher; ContentMatcher = contentMatcher; - ThrowException = throwException; _funcs = new[] { @@ -75,29 +72,27 @@ public class MimePartMatcher : IMatcher /// /// The MimePart. /// A value between 0.0 - 1.0 of the similarity. - public double IsMatch(MimePart mimePart) + public MatchResult IsMatch(MimePart mimePart) { - var match = MatchScores.Mismatch; + var score = MatchScores.Mismatch; + Exception? exception = null; try { - if (Array.TrueForAll(_funcs, func => MatchScores.IsPerfect(func(mimePart)))) + if (Array.TrueForAll(_funcs, func => func(mimePart).IsPerfect())) { - match = MatchScores.Perfect; + score = MatchScores.Perfect; } } - catch + catch (Exception ex) { - if (ThrowException) - { - throw; - } + exception = ex; } - return MatchBehaviourHelper.Convert(MatchBehaviour, match); + return new MatchResult(MatchBehaviourHelper.Convert(MatchBehaviour, score), exception); } - private double MatchOnContent(MimePart mimePart) + private MatchResult MatchOnContent(MimePart mimePart) { if (ContentMatcher == null) { diff --git a/src/WireMock.Net/Matchers/NotNullOrEmptyMatcher.cs b/src/WireMock.Net/Matchers/NotNullOrEmptyMatcher.cs index b45c7fe7..4f7ee89f 100644 --- a/src/WireMock.Net/Matchers/NotNullOrEmptyMatcher.cs +++ b/src/WireMock.Net/Matchers/NotNullOrEmptyMatcher.cs @@ -11,15 +11,12 @@ namespace WireMock.Matchers; /// public class NotNullOrEmptyMatcher : IObjectMatcher, IStringMatcher { - /// - public string Name => "NotNullOrEmptyMatcher"; + /// + public string Name => nameof(NotNullOrEmptyMatcher); - /// + /// public MatchBehaviour MatchBehaviour { get; } - /// - public bool ThrowException { get; } - /// /// Initializes a new instance of the class. /// @@ -29,8 +26,8 @@ public class NotNullOrEmptyMatcher : IObjectMatcher, IStringMatcher MatchBehaviour = matchBehaviour; } - /// - public double IsMatch(object? input) + /// + public MatchResult IsMatch(object? input) { bool match; @@ -52,15 +49,15 @@ public class NotNullOrEmptyMatcher : IObjectMatcher, IStringMatcher return MatchBehaviourHelper.Convert(MatchBehaviour, MatchScores.ToScore(match)); } - /// - public double IsMatch(string? input) + /// + public MatchResult IsMatch(string? input) { var match = !string.IsNullOrEmpty(input); return MatchBehaviourHelper.Convert(MatchBehaviour, MatchScores.ToScore(match)); } - /// + /// public AnyOf[] GetPatterns() { return EmptyArray>.Value; diff --git a/src/WireMock.Net/Matchers/RegexMatcher.cs b/src/WireMock.Net/Matchers/RegexMatcher.cs index fb20eeae..67c6fdf3 100644 --- a/src/WireMock.Net/Matchers/RegexMatcher.cs +++ b/src/WireMock.Net/Matchers/RegexMatcher.cs @@ -20,27 +20,22 @@ public class RegexMatcher : IStringMatcher, IIgnoreCaseMatcher private readonly AnyOf[] _patterns; private readonly Regex[] _expressions; - /// + /// public MatchBehaviour MatchBehaviour { get; } - /// - public bool ThrowException { get; } - /// /// Initializes a new instance of the class. /// /// The pattern. /// Ignore the case from the pattern. - /// Throw an exception when the internal matching fails because of invalid input. /// Use RegexExtended (default = true). /// The to use. (default = "Or") public RegexMatcher( [RegexPattern] AnyOf pattern, bool ignoreCase = false, - bool throwException = false, bool useRegexExtended = true, MatchOperator matchOperator = MatchOperator.Or) : - this(MatchBehaviour.AcceptOnMatch, new[] { pattern }, ignoreCase, throwException, useRegexExtended, matchOperator) + this(MatchBehaviour.AcceptOnMatch, new[] { pattern }, ignoreCase, useRegexExtended, matchOperator) { } @@ -50,17 +45,15 @@ public class RegexMatcher : IStringMatcher, IIgnoreCaseMatcher /// The match behaviour. /// The pattern. /// Ignore the case from the pattern. - /// Throw an exception when the internal matching fails because of invalid input. /// Use RegexExtended (default = true). /// The to use. (default = "Or") public RegexMatcher( MatchBehaviour matchBehaviour, [RegexPattern] AnyOf pattern, bool ignoreCase = false, - bool throwException = false, bool useRegexExtended = true, MatchOperator matchOperator = MatchOperator.Or) : - this(matchBehaviour, new[] { pattern }, ignoreCase, throwException, useRegexExtended, matchOperator) + this(matchBehaviour, new[] { pattern }, ignoreCase, useRegexExtended, matchOperator) { } @@ -70,21 +63,18 @@ public class RegexMatcher : IStringMatcher, IIgnoreCaseMatcher /// The match behaviour. /// The patterns. /// Ignore the case from the pattern. - /// Throw an exception when the internal matching fails because of invalid input. /// Use RegexExtended (default = true). /// The to use. (default = "Or") public RegexMatcher( MatchBehaviour matchBehaviour, [RegexPattern] AnyOf[] patterns, bool ignoreCase = false, - bool throwException = false, bool useRegexExtended = true, MatchOperator matchOperator = MatchOperator.Or) { _patterns = Guard.NotNull(patterns); IgnoreCase = ignoreCase; MatchBehaviour = matchBehaviour; - ThrowException = throwException; MatchOperator = matchOperator; RegexOptions options = RegexOptions.Compiled | RegexOptions.Multiline; @@ -97,26 +87,25 @@ public class RegexMatcher : IStringMatcher, IIgnoreCaseMatcher _expressions = patterns.Select(p => useRegexExtended ? new RegexExtended(p.GetPattern(), options) : new Regex(p.GetPattern(), options)).ToArray(); } - /// - public virtual double IsMatch(string? input) + /// + public virtual MatchResult IsMatch(string? input) { - double match = MatchScores.Mismatch; + var score = MatchScores.Mismatch; + Exception? exception = null; + if (input != null) { try { - match = MatchScores.ToScore(_expressions.Select(e => e.IsMatch(input)).ToArray(), MatchOperator); + score = MatchScores.ToScore(_expressions.Select(e => e.IsMatch(input)).ToArray(), MatchOperator); } - catch (Exception) + catch (Exception ex) { - if (ThrowException) - { - throw; - } + exception = ex; } } - return MatchBehaviourHelper.Convert(MatchBehaviour, match); + return new MatchResult(MatchBehaviourHelper.Convert(MatchBehaviour, score), exception); } /// diff --git a/src/WireMock.Net/Matchers/Request/RequestMatchResult.cs b/src/WireMock.Net/Matchers/Request/RequestMatchResult.cs index 0f516ce5..ac83a3fd 100644 --- a/src/WireMock.Net/Matchers/Request/RequestMatchResult.cs +++ b/src/WireMock.Net/Matchers/Request/RequestMatchResult.cs @@ -9,30 +9,25 @@ namespace WireMock.Matchers.Request; /// public class RequestMatchResult : IRequestMatchResult { - /// + /// public double TotalScore => MatchDetails.Sum(md => md.Score); - /// + /// public int TotalNumber => MatchDetails.Count; - /// + /// public bool IsPerfectMatch => Math.Abs(TotalScore - TotalNumber) < MatchScores.Tolerance; - /// - public double AverageTotalScore => TotalNumber == 0 ? 0.0 : TotalScore / TotalNumber; + /// + public double AverageTotalScore => TotalNumber == 0 ? MatchScores.Mismatch : TotalScore / TotalNumber; - /// + /// public IList MatchDetails { get; } = new List(); - /// - /// Adds the score. - /// - /// The matcher Type. - /// The score. - /// The score. - public double AddScore(Type matcherType, double score) + /// + public double AddScore(Type matcherType, double score, Exception? exception) { - MatchDetails.Add(new MatchDetail { MatcherType = matcherType, Score = score }); + MatchDetails.Add(new MatchDetail { MatcherType = matcherType, Score = score, Exception = exception }); return score; } @@ -44,11 +39,16 @@ public class RequestMatchResult : IRequestMatchResult /// /// A value that indicates the relative order of the objects being compared. The return value has these meanings: Value Meaning Less than zero This instance precedes in the sort order. Zero This instance occurs in the same position in the sort order as . Greater than zero This instance follows in the sort order. /// - public int CompareTo(object obj) + public int CompareTo(object? obj) { + if (obj == null) + { + return -1; + } + var compareObj = (RequestMatchResult)obj; - int averageTotalScoreResult = compareObj.AverageTotalScore.CompareTo(AverageTotalScore); + var averageTotalScoreResult = compareObj.AverageTotalScore.CompareTo(AverageTotalScore); // In case the score is equal, prefer the one with the most matchers. return averageTotalScoreResult == 0 ? compareObj.TotalNumber.CompareTo(TotalNumber) : averageTotalScoreResult; diff --git a/src/WireMock.Net/Matchers/Request/RequestMessageBodyMatcher.cs b/src/WireMock.Net/Matchers/Request/RequestMessageBodyMatcher.cs index 7bcb4138..f276da47 100644 --- a/src/WireMock.Net/Matchers/Request/RequestMessageBodyMatcher.cs +++ b/src/WireMock.Net/Matchers/Request/RequestMessageBodyMatcher.cs @@ -145,16 +145,16 @@ public class RequestMessageBodyMatcher : IRequestMatcher /// public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult) { - double score = CalculateMatchScore(requestMessage); - return requestMatchResult.AddScore(GetType(), score); + var (score, exception) = CalculateMatchScore(requestMessage).Expand(); + return requestMatchResult.AddScore(GetType(), score, exception); } - private double CalculateMatchScore(IRequestMessage requestMessage) + private MatchResult CalculateMatchScore(IRequestMessage requestMessage) { - if (Matchers != null) + if (Matchers != null && Matchers.Any()) { - var matchersResult = Matchers.Select(matcher => BodyDataMatchScoreCalculator.CalculateMatchScore(requestMessage.BodyData, matcher)).ToArray(); - return MatchScores.ToScore(matchersResult, MatchOperator); + var results = Matchers.Select(matcher => BodyDataMatchScoreCalculator.CalculateMatchScore(requestMessage.BodyData, matcher)).ToArray(); + return MatchResult.From(results, MatchOperator); } if (Func != null) @@ -182,6 +182,6 @@ public class RequestMessageBodyMatcher : IRequestMatcher return MatchScores.ToScore(BodyDataFunc(requestMessage.BodyData)); } - return MatchScores.Mismatch; + return default; } } \ No newline at end of file diff --git a/src/WireMock.Net/Matchers/Request/RequestMessageClientIPMatcher.cs b/src/WireMock.Net/Matchers/Request/RequestMessageClientIPMatcher.cs index 264c054f..cafad3ca 100644 --- a/src/WireMock.Net/Matchers/Request/RequestMessageClientIPMatcher.cs +++ b/src/WireMock.Net/Matchers/Request/RequestMessageClientIPMatcher.cs @@ -43,7 +43,7 @@ public class RequestMessageClientIPMatcher : IRequestMatcher MatchOperator matchOperator, params string[] clientIPs) : this(matchBehaviour, matchOperator, clientIPs - .Select(clientIP => new WildcardMatcher(matchBehaviour, new AnyOf[] { clientIP }, false, false, matchOperator)) + .Select(clientIP => new WildcardMatcher(matchBehaviour, new AnyOf[] { clientIP }, false, matchOperator)) .Cast().ToArray()) { Behaviour = matchBehaviour; @@ -75,16 +75,16 @@ public class RequestMessageClientIPMatcher : IRequestMatcher /// public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult) { - double score = IsMatch(requestMessage); - return requestMatchResult.AddScore(GetType(), score); + var (score, exception) = GetMatchResult(requestMessage).Expand(); + return requestMatchResult.AddScore(GetType(), score, exception); } - private double IsMatch(IRequestMessage requestMessage) + private MatchResult GetMatchResult(IRequestMessage requestMessage) { if (Matchers != null) { var results = Matchers.Select(m => m.IsMatch(requestMessage.ClientIP)).ToArray(); - return MatchScores.ToScore(results, MatchOperator); + return MatchResult.From(results, MatchOperator); } if (Funcs != null) @@ -93,6 +93,6 @@ public class RequestMessageClientIPMatcher : IRequestMatcher return MatchScores.ToScore(results, MatchOperator); } - return MatchScores.Mismatch; + return default; } } \ No newline at end of file diff --git a/src/WireMock.Net/Matchers/Request/RequestMessageCookieMatcher.cs b/src/WireMock.Net/Matchers/Request/RequestMessageCookieMatcher.cs index 576927de..4cacde4e 100644 --- a/src/WireMock.Net/Matchers/Request/RequestMessageCookieMatcher.cs +++ b/src/WireMock.Net/Matchers/Request/RequestMessageCookieMatcher.cs @@ -88,11 +88,11 @@ public class RequestMessageCookieMatcher : IRequestMatcher /// public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult) { - double score = IsMatch(requestMessage); - return requestMatchResult.AddScore(GetType(), score); + var (score, exception) = GetMatchResult(requestMessage).Expand(); + return requestMatchResult.AddScore(GetType(), score, exception); } - private double IsMatch(IRequestMessage requestMessage) + private MatchResult GetMatchResult(IRequestMessage requestMessage) { if (requestMessage.Cookies == null) { @@ -109,7 +109,7 @@ public class RequestMessageCookieMatcher : IRequestMatcher if (Matchers == null) { - return MatchScores.Mismatch; + return default; } if (!cookies.ContainsKey(Name)) @@ -117,7 +117,6 @@ public class RequestMessageCookieMatcher : IRequestMatcher return MatchBehaviourHelper.Convert(_matchBehaviour, MatchScores.Mismatch); } - string value = cookies[Name]; - return Matchers.Max(m => m.IsMatch(value)); + return Matchers.Max(m => m.IsMatch(cookies[Name])); } } \ No newline at end of file diff --git a/src/WireMock.Net/Matchers/Request/RequestMessageGraphQLMatcher.cs b/src/WireMock.Net/Matchers/Request/RequestMessageGraphQLMatcher.cs index 653d2d90..96c2df0a 100644 --- a/src/WireMock.Net/Matchers/Request/RequestMessageGraphQLMatcher.cs +++ b/src/WireMock.Net/Matchers/Request/RequestMessageGraphQLMatcher.cs @@ -1,3 +1,4 @@ +using System.Collections.Generic; using System.Linq; using Stef.Validation; using WireMock.Types; @@ -64,11 +65,13 @@ public class RequestMessageGraphQLMatcher : IRequestMatcher /// public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult) { - var score = CalculateMatchScore(requestMessage); - return requestMatchResult.AddScore(GetType(), score); + var results = CalculateMatchResults(requestMessage); + var (score, exception) = MatchResult.From(results, MatchOperator).Expand(); + + return requestMatchResult.AddScore(GetType(), score, exception); } - private static double CalculateMatchScore(IRequestMessage requestMessage, IMatcher matcher) + private static MatchResult CalculateMatchResult(IRequestMessage requestMessage, IMatcher matcher) { // Check if the matcher is a IStringMatcher // If the body is a Json or a String, use the BodyAsString to match on. @@ -77,18 +80,12 @@ public class RequestMessageGraphQLMatcher : IRequestMatcher return stringMatcher.IsMatch(requestMessage.BodyData.BodyAsString); } - return MatchScores.Mismatch; + return default; } - private double CalculateMatchScore(IRequestMessage requestMessage) + private IReadOnlyList CalculateMatchResults(IRequestMessage requestMessage) { - if (Matchers == null) - { - return MatchScores.Mismatch; - } - - var matchersResult = Matchers.Select(matcher => CalculateMatchScore(requestMessage, matcher)).ToArray(); - return MatchScores.ToScore(matchersResult, MatchOperator); + return Matchers == null ? new[] { new MatchResult() } : Matchers.Select(matcher => CalculateMatchResult(requestMessage, matcher)).ToArray(); } #if GRAPHQL diff --git a/src/WireMock.Net/Matchers/Request/RequestMessageHeaderMatcher.cs b/src/WireMock.Net/Matchers/Request/RequestMessageHeaderMatcher.cs index bc3c6c15..cb7ec144 100644 --- a/src/WireMock.Net/Matchers/Request/RequestMessageHeaderMatcher.cs +++ b/src/WireMock.Net/Matchers/Request/RequestMessageHeaderMatcher.cs @@ -100,11 +100,11 @@ public class RequestMessageHeaderMatcher : IRequestMatcher /// public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult) { - double score = IsMatch(requestMessage); - return requestMatchResult.AddScore(GetType(), score); + var (score, exception) = GetMatchResult(requestMessage).Expand(); + return requestMatchResult.AddScore(GetType(), score, exception); } - private double IsMatch(IRequestMessage requestMessage) + private MatchResult GetMatchResult(IRequestMessage requestMessage) { if (requestMessage.Headers == null) { @@ -127,15 +127,15 @@ public class RequestMessageHeaderMatcher : IRequestMatcher return MatchBehaviourHelper.Convert(_matchBehaviour, MatchScores.Mismatch); } - var results = new List(); + var results = new List(); foreach (var matcher in Matchers) { - var resultsPerMatcher = headers[Name].Select(v => matcher.IsMatch(v)).ToArray(); + var resultsPerMatcher = headers[Name].Select(matcher.IsMatch).ToArray(); - results.Add(MatchScores.ToScore(resultsPerMatcher, MatchOperator.And)); + results.Add(MatchResult.From(resultsPerMatcher, MatchOperator.And)); } - return MatchScores.ToScore(results, MatchOperator); + return MatchResult.From(results, MatchOperator); } return MatchBehaviourHelper.Convert(_matchBehaviour, MatchScores.Mismatch); diff --git a/src/WireMock.Net/Matchers/Request/RequestMessageMethodMatcher.cs b/src/WireMock.Net/Matchers/Request/RequestMessageMethodMatcher.cs index 55864d2c..3bc18527 100644 --- a/src/WireMock.Net/Matchers/Request/RequestMessageMethodMatcher.cs +++ b/src/WireMock.Net/Matchers/Request/RequestMessageMethodMatcher.cs @@ -39,14 +39,9 @@ internal class RequestMessageMethodMatcher : IRequestMatcher /// public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult) - { - double score = MatchBehaviourHelper.Convert(MatchBehaviour, IsMatch(requestMessage)); - return requestMatchResult.AddScore(GetType(), score); - } - - private double IsMatch(IRequestMessage requestMessage) { var scores = Methods.Select(m => string.Equals(m, requestMessage.Method, StringComparison.OrdinalIgnoreCase)).ToArray(); - return MatchScores.ToScore(scores, MatchOperator); + var score = MatchScores.ToScore(scores, MatchOperator); + return requestMatchResult.AddScore(GetType(), score, null); } } \ No newline at end of file diff --git a/src/WireMock.Net/Matchers/Request/RequestMessageMultiPartMatcher.cs b/src/WireMock.Net/Matchers/Request/RequestMessageMultiPartMatcher.cs index 92c43694..4695cb71 100644 --- a/src/WireMock.Net/Matchers/Request/RequestMessageMultiPartMatcher.cs +++ b/src/WireMock.Net/Matchers/Request/RequestMessageMultiPartMatcher.cs @@ -1,7 +1,7 @@ +using System; using System.Collections.Generic; using System.Linq; using Stef.Validation; -using WireMock.Http; using WireMock.Util; namespace WireMock.Matchers.Request; @@ -54,27 +54,31 @@ public class RequestMessageMultiPartMatcher : IRequestMatcher #if !MIMEKIT throw new System.NotSupportedException("The MultiPartMatcher can not be used for .NETStandard1.3 or .NET Framework 4.6.1 or lower."); #else - var match = MatchScores.Mismatch; + var score = MatchScores.Mismatch; + Exception? exception = null; if (Matchers?.Any() != true) { - return requestMatchResult.AddScore(GetType(), match); + return requestMatchResult.AddScore(GetType(), score, null); + } + + if (!MimeKitUtils.TryGetMimeMessage(requestMessage, out var message)) + { + return requestMatchResult.AddScore(GetType(), score, null); } try { - var message = MimeKitUtils.GetMimeMessage(requestMessage.BodyData!, requestMessage.Headers![HttpKnownHeaderNames.ContentType].ToString()); - var mimePartMatchers = Matchers.OfType().ToArray(); foreach (var mimePart in message.BodyParts.OfType()) { - var matchesForMimePart = new List { MatchScores.Mismatch }; + var matchesForMimePart = new List { default }; matchesForMimePart.AddRange(mimePartMatchers.Select(matcher => matcher.IsMatch(mimePart))); - match = matchesForMimePart.Max(); + score = matchesForMimePart.Select(m => m.Score).Max(); - if (MatchScores.IsPerfect(match)) + if (MatchScores.IsPerfect(score)) { if (MatchOperator == MatchOperator.Or) { @@ -83,17 +87,17 @@ public class RequestMessageMultiPartMatcher : IRequestMatcher } else { - match = MatchScores.Mismatch; + score = MatchScores.Mismatch; break; } } } - catch + catch (Exception ex) { - // Empty + exception = ex; } - return requestMatchResult.AddScore(GetType(), match); + return requestMatchResult.AddScore(GetType(), score, exception); #endif } } \ No newline at end of file diff --git a/src/WireMock.Net/Matchers/Request/RequestMessageParamMatcher.cs b/src/WireMock.Net/Matchers/Request/RequestMessageParamMatcher.cs index 41311838..e8b451f4 100644 --- a/src/WireMock.Net/Matchers/Request/RequestMessageParamMatcher.cs +++ b/src/WireMock.Net/Matchers/Request/RequestMessageParamMatcher.cs @@ -54,7 +54,7 @@ public class RequestMessageParamMatcher : IRequestMatcher /// Defines if the key should be matched using case-ignore. /// The values. public RequestMessageParamMatcher(MatchBehaviour matchBehaviour, string key, bool ignoreCase, params string[]? values) : - this(matchBehaviour, key, ignoreCase, values?.Select(value => new ExactMatcher(matchBehaviour, ignoreCase, false, MatchOperator.And, value)).Cast().ToArray()) + this(matchBehaviour, key, ignoreCase, values?.Select(value => new ExactMatcher(matchBehaviour, ignoreCase, MatchOperator.And, value)).Cast().ToArray()) { } @@ -85,11 +85,11 @@ public class RequestMessageParamMatcher : IRequestMatcher /// public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult) { - double score = MatchBehaviourHelper.Convert(MatchBehaviour, IsMatch(requestMessage)); - return requestMatchResult.AddScore(GetType(), score); + var (score, exception) = GetMatchResult(requestMessage).Expand(); + return requestMatchResult.AddScore(GetType(), score, exception); } - private double IsMatch(IRequestMessage requestMessage) + private MatchResult GetMatchResult(IRequestMessage requestMessage) { if (Funcs != null) { @@ -100,7 +100,7 @@ public class RequestMessageParamMatcher : IRequestMatcher if (valuesPresentInRequestMessage == null) { // Key is not present at all, just return Mismatch - return MatchScores.Mismatch; + return default; } if (Matchers != null && Matchers.Any()) @@ -115,10 +115,10 @@ public class RequestMessageParamMatcher : IRequestMatcher return MatchScores.Perfect; } - return MatchScores.Mismatch; + return default; } - private double CalculateScore(IReadOnlyList matchers, WireMockList valuesPresentInRequestMessage) + private static MatchResult CalculateScore(IReadOnlyList matchers, WireMockList valuesPresentInRequestMessage) { var total = new List(); @@ -130,7 +130,7 @@ public class RequestMessageParamMatcher : IRequestMatcher double score = 0d; foreach (string valuePresentInRequestMessage in valuesPresentInRequestMessage) { - score += matcher.IsMatch(valuePresentInRequestMessage) / matcher.GetPatterns().Length; + score += matcher.IsMatch(valuePresentInRequestMessage).Score / matcher.GetPatterns().Length; } total.Add(score); @@ -140,11 +140,11 @@ public class RequestMessageParamMatcher : IRequestMatcher { foreach (string valuePresentInRequestMessage in valuesPresentInRequestMessage) { - double score = matchers.Max(m => m.IsMatch(valuePresentInRequestMessage)); + var score = matchers.Max(m => m.IsMatch(valuePresentInRequestMessage).Score); total.Add(score); } } - return total.Any() ? MatchScores.ToScore(total, MatchOperator.Average) : MatchScores.Mismatch; + return total.Any() ? MatchScores.ToScore(total, MatchOperator.Average) : default; } } \ No newline at end of file diff --git a/src/WireMock.Net/Matchers/Request/RequestMessagePathMatcher.cs b/src/WireMock.Net/Matchers/Request/RequestMessagePathMatcher.cs index aa61807c..87aac9de 100644 --- a/src/WireMock.Net/Matchers/Request/RequestMessagePathMatcher.cs +++ b/src/WireMock.Net/Matchers/Request/RequestMessagePathMatcher.cs @@ -43,7 +43,7 @@ public class RequestMessagePathMatcher : IRequestMatcher MatchOperator matchOperator, params string[] paths) : this(matchBehaviour, matchOperator, paths - .Select(path => new WildcardMatcher(matchBehaviour, new AnyOf[] { path }, false, false, matchOperator)) + .Select(path => new WildcardMatcher(matchBehaviour, new AnyOf[] { path }, false, matchOperator)) .Cast().ToArray()) { Behaviour = matchBehaviour; @@ -75,16 +75,16 @@ public class RequestMessagePathMatcher : IRequestMatcher /// public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult) { - double score = IsMatch(requestMessage); - return requestMatchResult.AddScore(GetType(), score); + var (score, exception) = GetMatchResult(requestMessage).Expand(); + return requestMatchResult.AddScore(GetType(), score, exception); } - private double IsMatch(IRequestMessage requestMessage) + private MatchResult GetMatchResult(IRequestMessage requestMessage) { if (Matchers != null) { var results = Matchers.Select(m => m.IsMatch(requestMessage.Path)).ToArray(); - return MatchScores.ToScore(results, MatchOperator); + return MatchResult.From(results, MatchOperator); } if (Funcs != null) @@ -93,6 +93,6 @@ public class RequestMessagePathMatcher : IRequestMatcher return MatchScores.ToScore(results, MatchOperator); } - return MatchScores.Mismatch; + return default; } } \ No newline at end of file diff --git a/src/WireMock.Net/Matchers/Request/RequestMessageScenarioAndStateMatcher.cs b/src/WireMock.Net/Matchers/Request/RequestMessageScenarioAndStateMatcher.cs index 00bb01ee..69babdb7 100644 --- a/src/WireMock.Net/Matchers/Request/RequestMessageScenarioAndStateMatcher.cs +++ b/src/WireMock.Net/Matchers/Request/RequestMessageScenarioAndStateMatcher.cs @@ -30,11 +30,10 @@ internal class RequestMessageScenarioAndStateMatcher : IRequestMatcher /// public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult) { - double score = IsMatch(); - return requestMatchResult.AddScore(GetType(), score); + return requestMatchResult.AddScore(GetType(), GetScore(), null); } - private double IsMatch() + private double GetScore() { return Equals(_executionConditionState, _nextState) ? MatchScores.Perfect : MatchScores.Mismatch; } diff --git a/src/WireMock.Net/Matchers/Request/RequestMessageUrlMatcher.cs b/src/WireMock.Net/Matchers/Request/RequestMessageUrlMatcher.cs index 762275ff..c12c06cd 100644 --- a/src/WireMock.Net/Matchers/Request/RequestMessageUrlMatcher.cs +++ b/src/WireMock.Net/Matchers/Request/RequestMessageUrlMatcher.cs @@ -43,7 +43,7 @@ public class RequestMessageUrlMatcher : IRequestMatcher MatchOperator matchOperator, params string[] urls) : this(matchBehaviour, matchOperator, urls - .Select(url => new WildcardMatcher(matchBehaviour, new AnyOf[] { url }, false, false, matchOperator)) + .Select(url => new WildcardMatcher(matchBehaviour, new AnyOf[] { url }, false, matchOperator)) .Cast().ToArray()) { Behaviour = matchBehaviour; @@ -75,16 +75,16 @@ public class RequestMessageUrlMatcher : IRequestMatcher /// public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult) { - double score = IsMatch(requestMessage); - return requestMatchResult.AddScore(GetType(), score); + var (score, exception) = GetMatchResult(requestMessage).Expand(); + return requestMatchResult.AddScore(GetType(), score, exception); } - private double IsMatch(IRequestMessage requestMessage) + private MatchResult GetMatchResult(IRequestMessage requestMessage) { if (Matchers != null) { var results = Matchers.Select(m => m.IsMatch(requestMessage.Url)).ToArray(); - return MatchScores.ToScore(results, MatchOperator); + return MatchResult.From(results, MatchOperator); } if (Funcs != null) @@ -93,6 +93,6 @@ public class RequestMessageUrlMatcher : IRequestMatcher return MatchScores.ToScore(results, MatchOperator); } - return MatchScores.Mismatch; + return default; } } \ No newline at end of file diff --git a/src/WireMock.Net/Matchers/SimMetricsMatcher.cs b/src/WireMock.Net/Matchers/SimMetricsMatcher.cs index 76085cae..0b0ef1b5 100644 --- a/src/WireMock.Net/Matchers/SimMetricsMatcher.cs +++ b/src/WireMock.Net/Matchers/SimMetricsMatcher.cs @@ -18,12 +18,9 @@ public class SimMetricsMatcher : IStringMatcher private readonly AnyOf[] _patterns; private readonly SimMetricType _simMetricType; - /// + /// public MatchBehaviour MatchBehaviour { get; } - /// - public bool ThrowException { get; } - /// /// Initializes a new instance of the class. /// @@ -67,24 +64,21 @@ public class SimMetricsMatcher : IStringMatcher /// The match behaviour. /// The patterns. /// The SimMetric Type - /// Throw an exception when the internal matching fails because of invalid input. /// The to use. (default = "Or") public SimMetricsMatcher( MatchBehaviour matchBehaviour, AnyOf[] patterns, SimMetricType simMetricType = SimMetricType.Levenstein, - bool throwException = false, MatchOperator matchOperator = MatchOperator.Average) { _patterns = Guard.NotNull(patterns); _simMetricType = simMetricType; MatchBehaviour = matchBehaviour; - ThrowException = throwException; MatchOperator = matchOperator; } - /// - public double IsMatch(string input) + /// + public MatchResult IsMatch(string? input) { IStringMetric stringMetricType = GetStringMetricType(); @@ -94,48 +88,30 @@ public class SimMetricsMatcher : IStringMatcher private IStringMetric GetStringMetricType() { - switch (_simMetricType) + return _simMetricType switch { - case SimMetricType.BlockDistance: - return new BlockDistance(); - case SimMetricType.ChapmanLengthDeviation: - return new ChapmanLengthDeviation(); - case SimMetricType.CosineSimilarity: - return new CosineSimilarity(); - case SimMetricType.DiceSimilarity: - return new DiceSimilarity(); - case SimMetricType.EuclideanDistance: - return new EuclideanDistance(); - case SimMetricType.JaccardSimilarity: - return new JaccardSimilarity(); - case SimMetricType.Jaro: - return new Jaro(); - case SimMetricType.JaroWinkler: - return new JaroWinkler(); - case SimMetricType.MatchingCoefficient: - return new MatchingCoefficient(); - case SimMetricType.MongeElkan: - return new MongeElkan(); - case SimMetricType.NeedlemanWunch: - return new NeedlemanWunch(); - case SimMetricType.OverlapCoefficient: - return new OverlapCoefficient(); - case SimMetricType.QGramsDistance: - return new QGramsDistance(); - case SimMetricType.SmithWaterman: - return new SmithWaterman(); - case SimMetricType.SmithWatermanGotoh: - return new SmithWatermanGotoh(); - case SimMetricType.SmithWatermanGotohWindowedAffine: - return new SmithWatermanGotohWindowedAffine(); - case SimMetricType.ChapmanMeanLength: - return new ChapmanMeanLength(); - default: - return new Levenstein(); - } + SimMetricType.BlockDistance => new BlockDistance(), + SimMetricType.ChapmanLengthDeviation => new ChapmanLengthDeviation(), + SimMetricType.CosineSimilarity => new CosineSimilarity(), + SimMetricType.DiceSimilarity => new DiceSimilarity(), + SimMetricType.EuclideanDistance => new EuclideanDistance(), + SimMetricType.JaccardSimilarity => new JaccardSimilarity(), + SimMetricType.Jaro => new Jaro(), + SimMetricType.JaroWinkler => new JaroWinkler(), + SimMetricType.MatchingCoefficient => new MatchingCoefficient(), + SimMetricType.MongeElkan => new MongeElkan(), + SimMetricType.NeedlemanWunch => new NeedlemanWunch(), + SimMetricType.OverlapCoefficient => new OverlapCoefficient(), + SimMetricType.QGramsDistance => new QGramsDistance(), + SimMetricType.SmithWaterman => new SmithWaterman(), + SimMetricType.SmithWatermanGotoh => new SmithWatermanGotoh(), + SimMetricType.SmithWatermanGotohWindowedAffine => new SmithWatermanGotohWindowedAffine(), + SimMetricType.ChapmanMeanLength => new ChapmanMeanLength(), + _ => new Levenstein() + }; } - /// + /// public AnyOf[] GetPatterns() { return _patterns; @@ -144,6 +120,6 @@ public class SimMetricsMatcher : IStringMatcher /// public MatchOperator MatchOperator { get; } = MatchOperator.Average; - /// + /// public string Name => $"SimMetricsMatcher.{_simMetricType}"; } \ No newline at end of file diff --git a/src/WireMock.Net/Matchers/WildcardMatcher.cs b/src/WireMock.Net/Matchers/WildcardMatcher.cs index 58593422..b71c7b87 100644 --- a/src/WireMock.Net/Matchers/WildcardMatcher.cs +++ b/src/WireMock.Net/Matchers/WildcardMatcher.cs @@ -49,15 +49,12 @@ public class WildcardMatcher : RegexMatcher /// The match behaviour. /// The patterns. /// IgnoreCase - /// Throw an exception when the internal matching fails because of invalid input. /// The to use. (default = "Or") public WildcardMatcher( MatchBehaviour matchBehaviour, AnyOf[] patterns, bool ignoreCase = false, - bool throwException = false, - MatchOperator matchOperator = MatchOperator.Or) : - base(matchBehaviour, CreateArray(patterns), ignoreCase, throwException, true, matchOperator) + MatchOperator matchOperator = MatchOperator.Or) : base(matchBehaviour, CreateArray(patterns), ignoreCase, true, matchOperator) { _patterns = Guard.NotNull(patterns); } diff --git a/src/WireMock.Net/Matchers/XPathMatcher.cs b/src/WireMock.Net/Matchers/XPathMatcher.cs index a15a3edd..8bf0d7ae 100644 --- a/src/WireMock.Net/Matchers/XPathMatcher.cs +++ b/src/WireMock.Net/Matchers/XPathMatcher.cs @@ -1,6 +1,8 @@ using System; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Xml; +using System.Xml.XPath; using AnyOfTypes; using WireMock.Extensions; using WireMock.Models; @@ -9,86 +11,91 @@ using Stef.Validation; using Wmhelp.XPath2; #endif -namespace WireMock.Matchers +namespace WireMock.Matchers; + +/// +/// XPath2Matcher +/// +/// +public class XPathMatcher : IStringMatcher { + private readonly AnyOf[] _patterns; + + /// + public MatchBehaviour MatchBehaviour { get; } + /// - /// XPath2Matcher + /// Initializes a new instance of the class. /// - /// - public class XPathMatcher : IStringMatcher + /// The patterns. + public XPathMatcher(params AnyOf[] patterns) : this(MatchBehaviour.AcceptOnMatch, MatchOperator.Or, patterns) { - private readonly AnyOf[] _patterns; + } - /// - public MatchBehaviour MatchBehaviour { get; } + /// + /// Initializes a new instance of the class. + /// + /// The match behaviour. + /// The to use. (default = "Or") + /// The patterns. + public XPathMatcher( + MatchBehaviour matchBehaviour, + MatchOperator matchOperator = MatchOperator.Or, + params AnyOf[] patterns) + { + _patterns = Guard.NotNull(patterns); + MatchBehaviour = matchBehaviour; + MatchOperator = matchOperator; + } - /// - public bool ThrowException { get; } + /// + public MatchResult IsMatch(string? input) + { + var score = MatchScores.Mismatch; + Exception? exception = null; - /// - /// Initializes a new instance of the class. - /// - /// The patterns. - public XPathMatcher(params AnyOf[] patterns) : this(MatchBehaviour.AcceptOnMatch, false, MatchOperator.Or, patterns) + if (input != null && TryGetXPathNavigator(input, out var nav)) { - } - - /// - /// Initializes a new instance of the class. - /// - /// The match behaviour. - /// Throw an exception when the internal matching fails because of invalid input. - /// The to use. (default = "Or") - /// The patterns. - public XPathMatcher( - MatchBehaviour matchBehaviour, - bool throwException = false, - MatchOperator matchOperator = MatchOperator.Or, - params AnyOf[] patterns) - { - _patterns = Guard.NotNull(patterns); - MatchBehaviour = matchBehaviour; - ThrowException = throwException; - MatchOperator = matchOperator; - } - - /// - public double IsMatch(string? input) - { - double match = MatchScores.Mismatch; - if (input != null) + try { - try - { - var nav = new XmlDocument { InnerXml = input }.CreateNavigator(); #if NETSTANDARD1_3 - match = MatchScores.ToScore(_patterns.Select(p => true.Equals(nav.Evaluate($"boolean({p.GetPattern()})"))).ToArray(), MatchOperator); + score = MatchScores.ToScore(_patterns.Select(p => true.Equals(nav.Evaluate($"boolean({p.GetPattern()})"))).ToArray(), MatchOperator); #else - match = MatchScores.ToScore(_patterns.Select(p => true.Equals(nav.XPath2Evaluate($"boolean({p.GetPattern()})"))).ToArray(), MatchOperator); + score = MatchScores.ToScore(_patterns.Select(p => true.Equals(nav.XPath2Evaluate($"boolean({p.GetPattern()})"))).ToArray(), MatchOperator); #endif - } - catch (Exception) - { - if (ThrowException) - { - throw; - } - } } - - return MatchBehaviourHelper.Convert(MatchBehaviour, match); + catch (Exception ex) + { + exception = ex; + } } - /// - public AnyOf[] GetPatterns() + return new MatchResult(MatchBehaviourHelper.Convert(MatchBehaviour, score), exception); + } + + /// + public AnyOf[] GetPatterns() + { + return _patterns; + } + + /// + public MatchOperator MatchOperator { get; } + + /// + public string Name => nameof(XPathMatcher); + + private static bool TryGetXPathNavigator(string input, [NotNullWhen(true)] out XPathNavigator? nav) + { + try { - return _patterns; + nav = new XmlDocument { InnerXml = input }.CreateNavigator()!; + return true; + } + catch + { + nav = default; + return false; } - - /// - public MatchOperator MatchOperator { get; } - - /// - public string Name => "XPathMatcher"; } } \ No newline at end of file diff --git a/src/WireMock.Net/Owin/GlobalExceptionMiddleware.cs b/src/WireMock.Net/Owin/GlobalExceptionMiddleware.cs index 51f99acf..7b8dfcc0 100644 --- a/src/WireMock.Net/Owin/GlobalExceptionMiddleware.cs +++ b/src/WireMock.Net/Owin/GlobalExceptionMiddleware.cs @@ -67,7 +67,7 @@ namespace WireMock.Owin catch (Exception ex) { _options.Logger.Error("HttpStatusCode set to 500 {0}", ex); - await _responseMapper.MapAsync(ResponseMessageBuilder.Create(JsonConvert.SerializeObject(ex), 500), ctx.Response).ConfigureAwait(false); + await _responseMapper.MapAsync(ResponseMessageBuilder.Create(500, JsonConvert.SerializeObject(ex)), ctx.Response).ConfigureAwait(false); } } } diff --git a/src/WireMock.Net/Owin/Mappers/OwinResponseMapper.cs b/src/WireMock.Net/Owin/Mappers/OwinResponseMapper.cs index 44857333..5062117f 100644 --- a/src/WireMock.Net/Owin/Mappers/OwinResponseMapper.cs +++ b/src/WireMock.Net/Owin/Mappers/OwinResponseMapper.cs @@ -50,7 +50,7 @@ namespace WireMock.Owin.Mappers _options = Guard.NotNull(options); } - /// + /// public async Task MapAsync(IResponseMessage? responseMessage, IResponse response) { if (responseMessage == null) @@ -134,10 +134,8 @@ namespace WireMock.Owin.Mappers return (responseMessage.BodyData.Encoding ?? _utf8NoBom).GetBytes(responseMessage.BodyData.BodyAsString!); case BodyType.Json: - var formatting = responseMessage.BodyData.BodyAsJsonIndented == true - ? Formatting.Indented - : Formatting.None; - string jsonBody = JsonConvert.SerializeObject(responseMessage.BodyData.BodyAsJson, new JsonSerializerSettings { Formatting = formatting, NullValueHandling = NullValueHandling.Ignore }); + var formatting = responseMessage.BodyData.BodyAsJsonIndented == true ? Formatting.Indented : Formatting.None; + var jsonBody = JsonConvert.SerializeObject(responseMessage.BodyData.BodyAsJson, new JsonSerializerSettings { Formatting = formatting, NullValueHandling = NullValueHandling.Ignore }); return (responseMessage.BodyData.Encoding ?? _utf8NoBom).GetBytes(jsonBody); case BodyType.Bytes: diff --git a/src/WireMock.Net/Owin/MappingMatcher.cs b/src/WireMock.Net/Owin/MappingMatcher.cs index d979979c..230fe4d4 100644 --- a/src/WireMock.Net/Owin/MappingMatcher.cs +++ b/src/WireMock.Net/Owin/MappingMatcher.cs @@ -35,15 +35,32 @@ internal class MappingMatcher : IMappingMatcher { var nextState = GetNextState(mapping); - possibleMappings.Add(new MappingMatcherResult + var mappingMatcherResult = new MappingMatcherResult { Mapping = mapping, RequestMatchResult = mapping.GetRequestMatchResult(request, nextState) - }); + }; + + var exceptions = mappingMatcherResult.RequestMatchResult.MatchDetails + .Where(md => md.Exception != null) + .Select(md => md.Exception) + .ToArray(); + + if (!exceptions.Any()) + { + possibleMappings.Add(mappingMatcherResult); + } + else if (!request.AbsolutePath.StartsWith("/__admin", StringComparison.OrdinalIgnoreCase)) + { + foreach (var ex in exceptions) + { + LogException(mapping, ex!); + } + } } catch (Exception ex) { - _options.Logger.Error($"Getting a Request MatchResult for Mapping '{mapping.Guid}' failed. This mapping will not be evaluated. Exception: {ex}"); + LogException(mapping, ex); } } @@ -66,6 +83,11 @@ internal class MappingMatcher : IMappingMatcher return (match, partialMatch); } + private void LogException(IMapping mapping, Exception ex) + { + _options.Logger.Error($"Getting a Request MatchResult for Mapping '{mapping.Guid}' failed. This mapping will not be evaluated. Exception: {ex}"); + } + private string? GetNextState(IMapping mapping) { // If the mapping does not have a scenario or _options.Scenarios does not contain this scenario from the mapping, diff --git a/src/WireMock.Net/Owin/WireMockMiddleware.cs b/src/WireMock.Net/Owin/WireMockMiddleware.cs index 93658cae..3a438d9f 100644 --- a/src/WireMock.Net/Owin/WireMockMiddleware.cs +++ b/src/WireMock.Net/Owin/WireMockMiddleware.cs @@ -12,6 +12,8 @@ using WireMock.Types; using WireMock.ResponseBuilders; using WireMock.Settings; using System.Collections.Generic; +using WireMock.Constants; +using WireMock.Util; #if !USE_ASPNETCORE using IContext = Microsoft.Owin.IOwinContext; using OwinMiddleware = Microsoft.Owin.OwinMiddleware; @@ -105,7 +107,7 @@ namespace WireMock.Owin { logRequest = true; _options.Logger.Warn("HttpStatusCode set to 404 : No matching mapping found"); - response = ResponseMessageBuilder.Create("No matching mapping found", 404); + response = ResponseMessageBuilder.Create(HttpStatusCode.NotFound, WireMockConstants.NoMatchingFound); return; } @@ -113,11 +115,11 @@ namespace WireMock.Owin if (targetMapping.IsAdminInterface && _options.AuthenticationMatcher != null && request.Headers != null) { - bool present = request.Headers.TryGetValue(HttpKnownHeaderNames.Authorization, out WireMockList authorization); - if (!present || _options.AuthenticationMatcher.IsMatch(authorization!.ToString()) < MatchScores.Perfect) + bool present = request.Headers.TryGetValue(HttpKnownHeaderNames.Authorization, out WireMockList? authorization); + if (!present || _options.AuthenticationMatcher.IsMatch(authorization!.ToString()).Score < MatchScores.Perfect) { _options.Logger.Error("HttpStatusCode set to 401"); - response = ResponseMessageBuilder.Create(null, HttpStatusCode.Unauthorized); + response = ResponseMessageBuilder.Create(HttpStatusCode.Unauthorized, null); return; } } @@ -161,8 +163,8 @@ namespace WireMock.Owin } catch (Exception ex) { - _options.Logger.Error($"Providing a Response for Mapping '{result.Match?.Mapping?.Guid}' failed. HttpStatusCode set to 500. Exception: {ex}"); - response = ResponseMessageBuilder.Create(ex.Message, 500); + _options.Logger.Error($"Providing a Response for Mapping '{result.Match?.Mapping.Guid}' failed. HttpStatusCode set to 500. Exception: {ex}"); + response = ResponseMessageBuilder.Create(500, ex.Message); } finally { @@ -196,7 +198,17 @@ namespace WireMock.Owin // Empty catch } - await _responseMapper.MapAsync(response, ctx.Response).ConfigureAwait(false); + try + { + await _responseMapper.MapAsync(response, ctx.Response).ConfigureAwait(false); + } + catch (Exception ex) + { + _options.Logger.Error("HttpStatusCode set to 404 : No matching mapping found", ex); + + var notFoundResponse = ResponseMessageBuilder.Create(HttpStatusCode.NotFound, WireMockConstants.NoMatchingFound); + await _responseMapper.MapAsync(notFoundResponse, ctx.Response).ConfigureAwait(false); + } } await CompletedTask.ConfigureAwait(false); diff --git a/src/WireMock.Net/RequestMessage.cs b/src/WireMock.Net/RequestMessage.cs index 069d7801..ab1a6c0e 100644 --- a/src/WireMock.Net/RequestMessage.cs +++ b/src/WireMock.Net/RequestMessage.cs @@ -177,25 +177,29 @@ public class RequestMessage : IRequestMessage DetectedBodyTypeFromContentType = BodyData?.DetectedBodyTypeFromContentType.ToString(); DetectedCompression = BodyData?.DetectedCompression; -#if MIMEKIT - try - { - BodyAsMimeMessage = MimeKitUtils.GetMimeMessage(BodyData, headers![HttpKnownHeaderNames.ContentType].First()); - } - catch - { - // Ignore exception from MimeMessage.Load - } -#endif - Headers = headers?.ToDictionary(header => header.Key, header => new WireMockList(header.Value)); Cookies = cookies; RawQuery = urlDetails.Url.Query; Query = QueryStringParser.Parse(RawQuery, options?.QueryParameterMultipleValueSupport); QueryIgnoreCase = new Dictionary>(Query, StringComparer.OrdinalIgnoreCase); + #if USE_ASPNETCORE ClientCertificate = clientCertificate; #endif + +#if MIMEKIT + try + { + if (MimeKitUtils.TryGetMimeMessage(this, out var mimeMessage)) + { + BodyAsMimeMessage = mimeMessage; + } + } + catch + { + // Ignore exception from MimeMessage.Load + } +#endif } /// diff --git a/src/WireMock.Net/ResponseMessageBuilder.cs b/src/WireMock.Net/ResponseMessageBuilder.cs index dac1a360..f1c7120b 100644 --- a/src/WireMock.Net/ResponseMessageBuilder.cs +++ b/src/WireMock.Net/ResponseMessageBuilder.cs @@ -16,12 +16,17 @@ internal static class ResponseMessageBuilder { HttpKnownHeaderNames.ContentType, new WireMockList { WireMockConstants.ContentTypeJson } } }; - internal static ResponseMessage Create(string? message, HttpStatusCode statusCode, Guid? guid = null) + internal static ResponseMessage Create(HttpStatusCode statusCode, string? status, Guid? guid = null) { - return Create(message, (int)statusCode, guid); + return Create((int)statusCode, status, guid); } - internal static ResponseMessage Create(string? message, int statusCode = 200, Guid? guid = null) + internal static ResponseMessage Create(int statusCode, string? status, Guid? guid = null) + { + return Create(statusCode, status, null, guid); + } + + internal static ResponseMessage Create(int statusCode, string? status, string? error, Guid? guid = null) { var response = new ResponseMessage { @@ -29,7 +34,7 @@ internal static class ResponseMessageBuilder Headers = ContentTypeJsonHeaders }; - if (message != null) + if (status != null || error != null) { response.BodyData = new BodyData { @@ -37,7 +42,8 @@ internal static class ResponseMessageBuilder BodyAsJson = new StatusModel { Guid = guid, - Status = message + Status = status, + Error = error } }; } @@ -45,7 +51,7 @@ internal static class ResponseMessageBuilder return response; } - internal static ResponseMessage Create(int statusCode) + internal static ResponseMessage Create(HttpStatusCode statusCode) { return new ResponseMessage { diff --git a/src/WireMock.Net/Serialization/MappingConverter.cs b/src/WireMock.Net/Serialization/MappingConverter.cs index 3a356b4c..6b45b6a6 100644 --- a/src/WireMock.Net/Serialization/MappingConverter.cs +++ b/src/WireMock.Net/Serialization/MappingConverter.cs @@ -139,7 +139,6 @@ internal class MappingConverter sb.AppendLine(@$" .WithBody(new JsonPartialMatcher( value: {ToCSharpStringLiteral(jsonPartialMatcher.Value.ToString())}, ignoreCase: {ToCSharpBooleanLiteral(jsonPartialMatcher.IgnoreCase)}, - throwException: {ToCSharpBooleanLiteral(jsonPartialMatcher.ThrowException)}, regex: {ToCSharpBooleanLiteral(jsonPartialMatcher.Regex)} ))"); } @@ -148,7 +147,6 @@ internal class MappingConverter sb.AppendLine(@$" .WithBody(new JsonPartialWildcardMatcher( value: {ToCSharpStringLiteral(jsonPartialWildcardMatcher.Value.ToString())}, ignoreCase: {ToCSharpBooleanLiteral(jsonPartialWildcardMatcher.IgnoreCase)}, - throwException: {ToCSharpBooleanLiteral(jsonPartialWildcardMatcher.ThrowException)}, regex: {ToCSharpBooleanLiteral(jsonPartialWildcardMatcher.Regex)} ))"); } diff --git a/src/WireMock.Net/Serialization/MatcherMapper.cs b/src/WireMock.Net/Serialization/MatcherMapper.cs index 3ed1bc2a..4fb801b8 100644 --- a/src/WireMock.Net/Serialization/MatcherMapper.cs +++ b/src/WireMock.Net/Serialization/MatcherMapper.cs @@ -46,7 +46,6 @@ internal class MatcherMapper var matchBehaviour = matcher.RejectOnMatch == true ? MatchBehaviour.RejectOnMatch : MatchBehaviour.AcceptOnMatch; var matchOperator = StringUtils.ParseMatchOperator(matcher.MatchOperator); bool ignoreCase = matcher.IgnoreCase == true; - bool throwExceptionWhenMatcherFails = _settings.ThrowExceptionWhenMatcherFails == true; bool useRegexExtended = _settings.UseRegexExtended == true; bool useRegex = matcher.Regex == true; @@ -64,51 +63,51 @@ internal class MatcherMapper throw new NotSupportedException("It's not allowed to use the 'CSharpCodeMatcher' because WireMockServerSettings.AllowCSharpCodeMatcher is not set to 'true'."); case nameof(LinqMatcher): - return new LinqMatcher(matchBehaviour, throwExceptionWhenMatcherFails, matchOperator, stringPatterns); + return new LinqMatcher(matchBehaviour, matchOperator, stringPatterns); case nameof(ExactMatcher): - return new ExactMatcher(matchBehaviour, ignoreCase, throwExceptionWhenMatcherFails, matchOperator, stringPatterns); + return new ExactMatcher(matchBehaviour, ignoreCase, matchOperator, stringPatterns); case nameof(ExactObjectMatcher): - return CreateExactObjectMatcher(matchBehaviour, stringPatterns[0], throwExceptionWhenMatcherFails); + return CreateExactObjectMatcher(matchBehaviour, stringPatterns[0]); #if GRAPHQL case nameof(GraphQLMatcher): - return new GraphQLMatcher(stringPatterns[0].GetPattern(), matchBehaviour, throwExceptionWhenMatcherFails, matchOperator); + return new GraphQLMatcher(stringPatterns[0].GetPattern(), matchBehaviour, matchOperator); #endif #if MIMEKIT case nameof(MimePartMatcher): - return CreateMimePartMatcher(matchBehaviour, matcher, throwExceptionWhenMatcherFails); + return CreateMimePartMatcher(matchBehaviour, matcher); #endif case nameof(RegexMatcher): - return new RegexMatcher(matchBehaviour, stringPatterns, ignoreCase, throwExceptionWhenMatcherFails, useRegexExtended, matchOperator); + return new RegexMatcher(matchBehaviour, stringPatterns, ignoreCase, useRegexExtended, matchOperator); case nameof(JsonMatcher): var valueForJsonMatcher = matcher.Pattern ?? matcher.Patterns; - return new JsonMatcher(matchBehaviour, valueForJsonMatcher!, ignoreCase, throwExceptionWhenMatcherFails); + return new JsonMatcher(matchBehaviour, valueForJsonMatcher!, ignoreCase); case nameof(JsonPartialMatcher): var valueForJsonPartialMatcher = matcher.Pattern ?? matcher.Patterns; - return new JsonPartialMatcher(matchBehaviour, valueForJsonPartialMatcher!, ignoreCase, throwExceptionWhenMatcherFails, useRegex); + return new JsonPartialMatcher(matchBehaviour, valueForJsonPartialMatcher!, ignoreCase, useRegex); case nameof(JsonPartialWildcardMatcher): var valueForJsonPartialWildcardMatcher = matcher.Pattern ?? matcher.Patterns; - return new JsonPartialWildcardMatcher(matchBehaviour, valueForJsonPartialWildcardMatcher!, ignoreCase, throwExceptionWhenMatcherFails, useRegex); + return new JsonPartialWildcardMatcher(matchBehaviour, valueForJsonPartialWildcardMatcher!, ignoreCase, useRegex); case nameof(JsonPathMatcher): - return new JsonPathMatcher(matchBehaviour, throwExceptionWhenMatcherFails, matchOperator, stringPatterns); + return new JsonPathMatcher(matchBehaviour, matchOperator, stringPatterns); case nameof(JmesPathMatcher): - return new JmesPathMatcher(matchBehaviour, throwExceptionWhenMatcherFails, matchOperator, stringPatterns); + return new JmesPathMatcher(matchBehaviour, matchOperator, stringPatterns); case nameof(XPathMatcher): - return new XPathMatcher(matchBehaviour, throwExceptionWhenMatcherFails, matchOperator, stringPatterns); + return new XPathMatcher(matchBehaviour, matchOperator, stringPatterns); case nameof(WildcardMatcher): - return new WildcardMatcher(matchBehaviour, stringPatterns, ignoreCase, throwExceptionWhenMatcherFails, matchOperator); + return new WildcardMatcher(matchBehaviour, stringPatterns, ignoreCase, matchOperator); case nameof(ContentTypeMatcher): - return new ContentTypeMatcher(matchBehaviour, stringPatterns, ignoreCase, throwExceptionWhenMatcherFails); + return new ContentTypeMatcher(matchBehaviour, stringPatterns, ignoreCase); case nameof(SimMetricsMatcher): SimMetricType type = SimMetricType.Levenstein; @@ -117,7 +116,7 @@ internal class MatcherMapper throw new NotSupportedException($"Matcher '{matcherName}' with Type '{matcherType}' is not supported."); } - return new SimMetricsMatcher(matchBehaviour, stringPatterns, type, throwExceptionWhenMatcherFails); + return new SimMetricsMatcher(matchBehaviour, stringPatterns, type); default: if (_settings.CustomMatcherMappings != null && _settings.CustomMatcherMappings.ContainsKey(matcherName)) @@ -236,7 +235,7 @@ internal class MatcherMapper return EmptyArray>.Value; } - private static ExactObjectMatcher CreateExactObjectMatcher(MatchBehaviour matchBehaviour, AnyOf stringPattern, bool throwException) + private static ExactObjectMatcher CreateExactObjectMatcher(MatchBehaviour matchBehaviour, AnyOf stringPattern) { byte[] bytePattern; try @@ -248,18 +247,18 @@ internal class MatcherMapper throw new ArgumentException($"Matcher 'ExactObjectMatcher' has invalid pattern. The pattern value '{stringPattern}' is not a Base64String.", nameof(stringPattern)); } - return new ExactObjectMatcher(matchBehaviour, bytePattern, throwException); + return new ExactObjectMatcher(matchBehaviour, bytePattern); } #if MIMEKIT - private MimePartMatcher CreateMimePartMatcher(MatchBehaviour matchBehaviour, MatcherModel? matcher, bool throwExceptionWhenMatcherFails) + private MimePartMatcher CreateMimePartMatcher(MatchBehaviour matchBehaviour, MatcherModel? matcher) { var contentTypeMatcher = Map(matcher?.ContentTypeMatcher) as IStringMatcher; var contentDispositionMatcher = Map(matcher?.ContentDispositionMatcher) as IStringMatcher; var contentTransferEncodingMatcher = Map(matcher?.ContentTransferEncodingMatcher) as IStringMatcher; var contentMatcher = Map(matcher?.ContentMatcher); - return new MimePartMatcher(matchBehaviour, contentTypeMatcher, contentDispositionMatcher, contentTransferEncodingMatcher, contentMatcher, throwExceptionWhenMatcherFails); + return new MimePartMatcher(matchBehaviour, contentTypeMatcher, contentDispositionMatcher, contentTransferEncodingMatcher, contentMatcher); } #endif } \ No newline at end of file diff --git a/src/WireMock.Net/Serialization/ProxyMappingConverter.cs b/src/WireMock.Net/Serialization/ProxyMappingConverter.cs index 0c5b2e53..3878c30f 100644 --- a/src/WireMock.Net/Serialization/ProxyMappingConverter.cs +++ b/src/WireMock.Net/Serialization/ProxyMappingConverter.cs @@ -30,8 +30,8 @@ internal class ProxyMappingConverter { var useDefinedRequestMatchers = proxyAndRecordSettings.UseDefinedRequestMatchers; var excludedHeaders = new List(proxyAndRecordSettings.ExcludedHeaders ?? new string[] { }) { "Cookie" }; - var excludedCookies = proxyAndRecordSettings.ExcludedCookies ?? new string[0]; - var excludedParams = proxyAndRecordSettings.ExcludedParams ?? new string[0]; + var excludedCookies = proxyAndRecordSettings.ExcludedCookies ?? EmptyArray.Value; + var excludedParams = proxyAndRecordSettings.ExcludedParams ?? EmptyArray.Value; var request = (Request?)mapping?.RequestMatcher; var clientIPMatcher = request?.GetRequestMessageMatcher(); @@ -137,7 +137,6 @@ internal class ProxyMappingConverter } // Body - bool throwExceptionWhenMatcherFails = _settings.ThrowExceptionWhenMatcherFails == true; if (useDefinedRequestMatchers && bodyMatcher?.Matchers is not null) { newRequest.WithBody(bodyMatcher.Matchers); @@ -147,16 +146,16 @@ internal class ProxyMappingConverter switch (requestMessage.BodyData?.DetectedBodyType) { case BodyType.Json: - newRequest.WithBody(new JsonMatcher(MatchBehaviour.AcceptOnMatch, requestMessage.BodyData.BodyAsJson!, true, throwExceptionWhenMatcherFails)); + newRequest.WithBody(new JsonMatcher(MatchBehaviour.AcceptOnMatch, requestMessage.BodyData.BodyAsJson!, true)); break; case BodyType.String: case BodyType.FormUrlEncoded: - newRequest.WithBody(new ExactMatcher(MatchBehaviour.AcceptOnMatch, true, throwExceptionWhenMatcherFails, MatchOperator.Or, requestMessage.BodyData.BodyAsString!)); + newRequest.WithBody(new ExactMatcher(MatchBehaviour.AcceptOnMatch, true, MatchOperator.Or, requestMessage.BodyData.BodyAsString!)); break; case BodyType.Bytes: - newRequest.WithBody(new ExactObjectMatcher(MatchBehaviour.AcceptOnMatch, requestMessage.BodyData.BodyAsBytes!, throwExceptionWhenMatcherFails)); + newRequest.WithBody(new ExactObjectMatcher(MatchBehaviour.AcceptOnMatch, requestMessage.BodyData.BodyAsBytes!)); break; } } diff --git a/src/WireMock.Net/Server/WireMockServer.Admin.cs b/src/WireMock.Net/Server/WireMockServer.Admin.cs index 1864cc11..a0fce63e 100644 --- a/src/WireMock.Net/Server/WireMockServer.Admin.cs +++ b/src/WireMock.Net/Server/WireMockServer.Admin.cs @@ -237,7 +237,6 @@ public partial class WireMockServer ReadStaticMappings = _settings.ReadStaticMappings, RequestLogExpirationDuration = _settings.RequestLogExpirationDuration, SaveUnmatchedRequests = _settings.SaveUnmatchedRequests, - ThrowExceptionWhenMatcherFails = _settings.ThrowExceptionWhenMatcherFails, UseRegexExtended = _settings.UseRegexExtended, WatchStaticMappings = _settings.WatchStaticMappings, WatchStaticMappingsInSubdirectories = _settings.WatchStaticMappingsInSubdirectories, @@ -273,7 +272,6 @@ public partial class WireMockServer _settings.ReadStaticMappings = settings.ReadStaticMappings; _settings.RequestLogExpirationDuration = settings.RequestLogExpirationDuration; _settings.SaveUnmatchedRequests = settings.SaveUnmatchedRequests; - _settings.ThrowExceptionWhenMatcherFails = settings.ThrowExceptionWhenMatcherFails; _settings.UseRegexExtended = settings.UseRegexExtended; _settings.WatchStaticMappings = settings.WatchStaticMappings; _settings.WatchStaticMappingsInSubdirectories = settings.WatchStaticMappingsInSubdirectories; @@ -303,7 +301,7 @@ public partial class WireMockServer _options.AcceptAnyClientCertificate = _settings.AcceptAnyClientCertificate; #endif - return ResponseMessageBuilder.Create("Settings updated"); + return ResponseMessageBuilder.Create(200, "Settings updated"); } #endregion Settings @@ -314,7 +312,7 @@ public partial class WireMockServer if (mapping == null) { _settings.Logger.Warn("HttpStatusCode set to 404 : Mapping not found"); - return ResponseMessageBuilder.Create("Mapping not found", HttpStatusCode.NotFound); + return ResponseMessageBuilder.Create(HttpStatusCode.NotFound, "Mapping not found"); } var model = _mappingConverter.ToMappingModel(mapping); @@ -330,14 +328,14 @@ public partial class WireMockServer if (code is null) { _settings.Logger.Warn("HttpStatusCode set to 404 : Mapping not found"); - return ResponseMessageBuilder.Create("Mapping not found", HttpStatusCode.NotFound); + return ResponseMessageBuilder.Create(HttpStatusCode.NotFound, "Mapping not found"); } return ToResponseMessage(code); } _settings.Logger.Warn("HttpStatusCode set to 400"); - return ResponseMessageBuilder.Create("GUID is missing", HttpStatusCode.BadRequest); + return ResponseMessageBuilder.Create(HttpStatusCode.BadRequest, "GUID is missing"); } private static MappingConverterType GetMappingConverterType(IRequestMessage requestMessage) @@ -365,22 +363,22 @@ public partial class WireMockServer var mappingModel = DeserializeObject(requestMessage); var guidFromPut = ConvertMappingAndRegisterAsRespondProvider(mappingModel, guid); - return ResponseMessageBuilder.Create("Mapping added or updated", HttpStatusCode.OK, guidFromPut); + return ResponseMessageBuilder.Create(HttpStatusCode.OK, "Mapping added or updated", guidFromPut); } _settings.Logger.Warn("HttpStatusCode set to 404 : Mapping not found"); - return ResponseMessageBuilder.Create("Mapping not found", HttpStatusCode.NotFound); + return ResponseMessageBuilder.Create(HttpStatusCode.NotFound, "Mapping not found"); } private IResponseMessage MappingDelete(IRequestMessage requestMessage) { if (TryParseGuidFromRequestMessage(requestMessage, out var guid) && DeleteMapping(guid)) { - return ResponseMessageBuilder.Create("Mapping removed", HttpStatusCode.OK, guid); + return ResponseMessageBuilder.Create(HttpStatusCode.OK, "Mapping removed", guid); } _settings.Logger.Warn("HttpStatusCode set to 404 : Mapping not found"); - return ResponseMessageBuilder.Create("Mapping not found", HttpStatusCode.NotFound); + return ResponseMessageBuilder.Create(HttpStatusCode.NotFound, "Mapping not found"); } private static bool TryParseGuidFromRequestMessage(IRequestMessage requestMessage, out Guid guid) @@ -409,7 +407,7 @@ public partial class WireMockServer { SaveStaticMappings(); - return ResponseMessageBuilder.Create("Mappings saved to disk"); + return ResponseMessageBuilder.Create(200, "Mappings saved to disk"); } private MappingModel[] ToMappingModels() @@ -439,22 +437,22 @@ public partial class WireMockServer if (mappingModels.Length == 1) { Guid? guid = ConvertMappingAndRegisterAsRespondProvider(mappingModels[0]); - return ResponseMessageBuilder.Create("Mapping added", 201, guid); + return ResponseMessageBuilder.Create(201, "Mapping added", guid); } ConvertMappingsAndRegisterAsRespondProvider(mappingModels); - return ResponseMessageBuilder.Create("Mappings added", 201); + return ResponseMessageBuilder.Create(201, "Mappings added"); } catch (ArgumentException a) { _settings.Logger.Error("HttpStatusCode set to 400 {0}", a); - return ResponseMessageBuilder.Create(a.Message, 400); + return ResponseMessageBuilder.Create(400, a.Message); } catch (Exception e) { _settings.Logger.Error("HttpStatusCode set to 500 {0}", e); - return ResponseMessageBuilder.Create(e.ToString(), 500); + return ResponseMessageBuilder.Create(500, e.ToString()); } } @@ -465,18 +463,18 @@ public partial class WireMockServer var deletedGuids = MappingsDeleteMappingFromBody(requestMessage); if (deletedGuids != null) { - return ResponseMessageBuilder.Create($"Mappings deleted. Affected GUIDs: [{string.Join(", ", deletedGuids.ToArray())}]"); + return ResponseMessageBuilder.Create(200, $"Mappings deleted. Affected GUIDs: [{string.Join(", ", deletedGuids.ToArray())}]"); } // return bad request - return ResponseMessageBuilder.Create("Poorly formed mapping JSON.", 400); + return ResponseMessageBuilder.Create(400, "Poorly formed mapping JSON."); } ResetMappings(); ResetScenarios(); - return ResponseMessageBuilder.Create("Mappings deleted"); + return ResponseMessageBuilder.Create(200, "Mappings deleted"); } private IEnumerable? MappingsDeleteMappingFromBody(IRequestMessage requestMessage) @@ -528,7 +526,7 @@ public partial class WireMockServer message = $"{message} and static mappings reloaded"; } - return ResponseMessageBuilder.Create(message); + return ResponseMessageBuilder.Create(200, message); } #endregion Mappings @@ -546,18 +544,18 @@ public partial class WireMockServer } _settings.Logger.Warn("HttpStatusCode set to 404 : Request not found"); - return ResponseMessageBuilder.Create("Request not found", HttpStatusCode.NotFound); + return ResponseMessageBuilder.Create(HttpStatusCode.NotFound, "Request not found"); } private IResponseMessage RequestDelete(IRequestMessage requestMessage) { if (TryParseGuidFromRequestMessage(requestMessage, out var guid) && DeleteLogEntry(guid)) { - return ResponseMessageBuilder.Create("Request removed"); + return ResponseMessageBuilder.Create(200, "Request removed"); } _settings.Logger.Warn("HttpStatusCode set to 404 : Request not found"); - return ResponseMessageBuilder.Create("Request not found", HttpStatusCode.NotFound); + return ResponseMessageBuilder.Create(HttpStatusCode.NotFound, "Request not found"); } #endregion Request/{guid} @@ -576,7 +574,7 @@ public partial class WireMockServer { ResetLogEntries(); - return ResponseMessageBuilder.Create("Requests deleted"); + return ResponseMessageBuilder.Create(200, "Requests deleted"); } #endregion Requests @@ -623,7 +621,7 @@ public partial class WireMockServer { ResetScenarios(); - return ResponseMessageBuilder.Create("Scenarios reset"); + return ResponseMessageBuilder.Create(200, "Scenarios reset"); } private IResponseMessage ScenarioReset(IRequestMessage requestMessage) @@ -633,8 +631,8 @@ public partial class WireMockServer requestMessage.Path.Split('/').Reverse().Skip(1).First(); return ResetScenario(name) ? - ResponseMessageBuilder.Create("Scenario reset") : - ResponseMessageBuilder.Create($"No scenario found by name '{name}'.", HttpStatusCode.NotFound); + ResponseMessageBuilder.Create(200, "Scenario reset") : + ResponseMessageBuilder.Create(HttpStatusCode.NotFound, $"No scenario found by name '{name}'."); } #endregion diff --git a/src/WireMock.Net/Server/WireMockServer.AdminFiles.cs b/src/WireMock.Net/Server/WireMockServer.AdminFiles.cs index 6541cb78..9a085afa 100644 --- a/src/WireMock.Net/Server/WireMockServer.AdminFiles.cs +++ b/src/WireMock.Net/Server/WireMockServer.AdminFiles.cs @@ -1,5 +1,6 @@ using System.IO; using System.Linq; +using System.Net; using System.Text; using WireMock.Matchers; using WireMock.Types; @@ -25,7 +26,7 @@ namespace WireMock.Server _settings.FileSystemHandler.WriteFile(filename, requestMessage.BodyAsBytes); - return ResponseMessageBuilder.Create("File created"); + return ResponseMessageBuilder.Create(200, "File created"); } private IResponseMessage FilePut(IRequestMessage requestMessage) @@ -35,12 +36,12 @@ namespace WireMock.Server if (!_settings.FileSystemHandler.FileExists(filename)) { _settings.Logger.Info("The file '{0}' does not exist, updating file will be skipped.", filename); - return ResponseMessageBuilder.Create("File is not found", 404); + return ResponseMessageBuilder.Create(404, "File is not found"); } _settings.FileSystemHandler.WriteFile(filename, requestMessage.BodyAsBytes); - return ResponseMessageBuilder.Create("File updated"); + return ResponseMessageBuilder.Create(200, "File updated"); } private IResponseMessage FileGet(IRequestMessage requestMessage) @@ -50,7 +51,7 @@ namespace WireMock.Server if (!_settings.FileSystemHandler.FileExists(filename)) { _settings.Logger.Info("The file '{0}' does not exist.", filename); - return ResponseMessageBuilder.Create("File is not found", 404); + return ResponseMessageBuilder.Create(404, "File is not found"); } byte[] bytes = _settings.FileSystemHandler.ReadFile(filename); @@ -86,10 +87,10 @@ namespace WireMock.Server if (!_settings.FileSystemHandler.FileExists(filename)) { _settings.Logger.Info("The file '{0}' does not exist.", filename); - return ResponseMessageBuilder.Create(404); + return ResponseMessageBuilder.Create(HttpStatusCode.NotFound); } - return ResponseMessageBuilder.Create(204); + return ResponseMessageBuilder.Create(HttpStatusCode.NoContent); } private IResponseMessage FileDelete(IRequestMessage requestMessage) @@ -99,11 +100,11 @@ namespace WireMock.Server if (!_settings.FileSystemHandler.FileExists(filename)) { _settings.Logger.Info("The file '{0}' does not exist.", filename); - return ResponseMessageBuilder.Create("File is not deleted", 404); + return ResponseMessageBuilder.Create(404, "File is not deleted"); } _settings.FileSystemHandler.DeleteFile(filename); - return ResponseMessageBuilder.Create("File deleted."); + return ResponseMessageBuilder.Create(200, "File deleted."); } private string GetFileNameFromRequestMessage(IRequestMessage requestMessage) diff --git a/src/WireMock.Net/Server/WireMockServer.ImportWireMockOrg.cs b/src/WireMock.Net/Server/WireMockServer.ImportWireMockOrg.cs index 4ac38764..3b42051f 100644 --- a/src/WireMock.Net/Server/WireMockServer.ImportWireMockOrg.cs +++ b/src/WireMock.Net/Server/WireMockServer.ImportWireMockOrg.cs @@ -52,7 +52,7 @@ public partial class WireMockServer if (mappingModels.Length == 1) { Guid? guid = ConvertWireMockOrgMappingAndRegisterAsRespondProvider(mappingModels[0]); - return ResponseMessageBuilder.Create("Mapping added", 201, guid); + return ResponseMessageBuilder.Create(201, "Mapping added", guid); } foreach (var mappingModel in mappingModels) @@ -60,17 +60,17 @@ public partial class WireMockServer ConvertWireMockOrgMappingAndRegisterAsRespondProvider(mappingModel); } - return ResponseMessageBuilder.Create("Mappings added", 201); + return ResponseMessageBuilder.Create(201, "Mappings added"); } catch (ArgumentException a) { _settings.Logger.Error("HttpStatusCode set to 400 {0}", a); - return ResponseMessageBuilder.Create(a.Message, 400); + return ResponseMessageBuilder.Create(400, a.Message); } catch (Exception e) { _settings.Logger.Error("HttpStatusCode set to 500 {0}", e); - return ResponseMessageBuilder.Create(e.ToString(), 500); + return ResponseMessageBuilder.Create(500, e.ToString()); } } diff --git a/src/WireMock.Net/Server/WireMockServer.OpenApiParser.cs b/src/WireMock.Net/Server/WireMockServer.OpenApiParser.cs index 38284c61..99031917 100644 --- a/src/WireMock.Net/Server/WireMockServer.OpenApiParser.cs +++ b/src/WireMock.Net/Server/WireMockServer.OpenApiParser.cs @@ -1,7 +1,7 @@ +using System.Net; #if OPENAPIPARSER using System; using System.Linq; -using System.Net; using WireMock.Net.OpenApiParser; #endif @@ -14,16 +14,16 @@ public partial class WireMockServer #if OPENAPIPARSER try { - var mappingModels = new WireMockOpenApiParser().FromText(requestMessage.Body, out var diagnostic); + var mappingModels = new WireMockOpenApiParser().FromText(requestMessage.Body!, out var diagnostic); return diagnostic.Errors.Any() ? ToJson(diagnostic, false, HttpStatusCode.BadRequest) : ToJson(mappingModels); } catch (Exception e) { _settings.Logger.Error("HttpStatusCode set to {0} {1}", HttpStatusCode.BadRequest, e); - return ResponseMessageBuilder.Create(e.Message, HttpStatusCode.BadRequest); + return ResponseMessageBuilder.Create(HttpStatusCode.BadRequest, e.Message); } #else - return ResponseMessageBuilder.Create("Not supported for .NETStandard 1.3 and .NET 4.5.2 or lower.", 400); + return ResponseMessageBuilder.Create(HttpStatusCode.BadRequest, "Not supported for .NETStandard 1.3 and .NET 4.5.2 or lower."); #endif } @@ -32,7 +32,7 @@ public partial class WireMockServer #if OPENAPIPARSER try { - var mappingModels = new WireMockOpenApiParser().FromText(requestMessage.Body, out var diagnostic); + var mappingModels = new WireMockOpenApiParser().FromText(requestMessage.Body!, out var diagnostic); if (diagnostic.Errors.Any()) { return ToJson(diagnostic, false, HttpStatusCode.BadRequest); @@ -40,15 +40,15 @@ public partial class WireMockServer ConvertMappingsAndRegisterAsRespondProvider(mappingModels); - return ResponseMessageBuilder.Create("OpenApi document converted to Mappings", HttpStatusCode.Created); + return ResponseMessageBuilder.Create(HttpStatusCode.Created, "OpenApi document converted to Mappings"); } catch (Exception e) { _settings.Logger.Error("HttpStatusCode set to {0} {1}", HttpStatusCode.BadRequest, e); - return ResponseMessageBuilder.Create(e.Message, HttpStatusCode.BadRequest); + return ResponseMessageBuilder.Create(HttpStatusCode.BadRequest, e.Message); } #else - return ResponseMessageBuilder.Create("Not supported for .NETStandard 1.3 and .NET 4.5.2 or lower.", 400); + return ResponseMessageBuilder.Create(HttpStatusCode.BadRequest, "Not supported for .NETStandard 1.3 and .NET 4.5.2 or lower."); #endif } } \ No newline at end of file diff --git a/src/WireMock.Net/Server/WireMockServer.cs b/src/WireMock.Net/Server/WireMockServer.cs index 298716d8..0b982f9b 100644 --- a/src/WireMock.Net/Server/WireMockServer.cs +++ b/src/WireMock.Net/Server/WireMockServer.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; +using System.Net; using System.Net.Http; using System.Threading; using JetBrains.Annotations; @@ -11,6 +12,7 @@ using Newtonsoft.Json; using Stef.Validation; using WireMock.Admin.Mappings; using WireMock.Authentication; +using WireMock.Constants; using WireMock.Exceptions; using WireMock.Handlers; using WireMock.Http; @@ -391,7 +393,7 @@ public partial class WireMockServer : IWireMockServer Given(Request.Create().WithPath("/*").UsingAnyMethod()) .WithGuid(Guid.Parse("90008000-0000-4444-a17e-669cd84f1f05")) .AtPriority(1000) - .RespondWith(new DynamicResponseProvider(_ => ResponseMessageBuilder.Create("No matching mapping found", 404))); + .RespondWith(new DynamicResponseProvider(_ => ResponseMessageBuilder.Create(HttpStatusCode.NotFound, WireMockConstants.NoMatchingFound))); } /// diff --git a/src/WireMock.Net/Settings/WireMockServerSettings.cs b/src/WireMock.Net/Settings/WireMockServerSettings.cs index 3fb484ad..d944dfc1 100644 --- a/src/WireMock.Net/Settings/WireMockServerSettings.cs +++ b/src/WireMock.Net/Settings/WireMockServerSettings.cs @@ -221,12 +221,6 @@ public class WireMockServerSettings [PublicAPI] public bool? HandleRequestsSynchronously { get; set; } - /// - /// Throw an exception when the fails because of invalid input. (default set to false). - /// - [PublicAPI] - public bool? ThrowExceptionWhenMatcherFails { get; set; } - /// /// If https is used, these settings can be used to configure the CertificateSettings in case a custom certificate instead the default .NET certificate should be used. /// diff --git a/src/WireMock.Net/Settings/WireMockServerSettingsParser.cs b/src/WireMock.Net/Settings/WireMockServerSettingsParser.cs index d268cea9..08e18c26 100644 --- a/src/WireMock.Net/Settings/WireMockServerSettingsParser.cs +++ b/src/WireMock.Net/Settings/WireMockServerSettingsParser.cs @@ -57,7 +57,6 @@ public static class WireMockServerSettingsParser SaveUnmatchedRequests = parser.GetBoolValue(nameof(WireMockServerSettings.SaveUnmatchedRequests)), StartAdminInterface = parser.GetBoolValue("StartAdminInterface", true), StartTimeout = parser.GetIntValue(nameof(WireMockServerSettings.StartTimeout), WireMockServerSettings.DefaultStartTimeout), - ThrowExceptionWhenMatcherFails = parser.GetBoolValue("ThrowExceptionWhenMatcherFails"), UseRegexExtended = parser.GetBoolValue(nameof(WireMockServerSettings.UseRegexExtended), true), WatchStaticMappings = parser.GetBoolValue("WatchStaticMappings"), WatchStaticMappingsInSubdirectories = parser.GetBoolValue("WatchStaticMappingsInSubdirectories"), diff --git a/src/WireMock.Net/Util/BodyParser.cs b/src/WireMock.Net/Util/BodyParser.cs index 2a5ee6b8..5e7e037e 100644 --- a/src/WireMock.Net/Util/BodyParser.cs +++ b/src/WireMock.Net/Util/BodyParser.cs @@ -85,27 +85,27 @@ internal static class BodyParser public static BodyType DetectBodyTypeFromContentType(string? contentTypeValue) { - if (string.IsNullOrEmpty(contentTypeValue) || !MediaTypeHeaderValue.TryParse(contentTypeValue, out MediaTypeHeaderValue contentType)) + if (string.IsNullOrEmpty(contentTypeValue) || !MediaTypeHeaderValue.TryParse(contentTypeValue, out MediaTypeHeaderValue? contentType)) { return BodyType.Bytes; } - if (MatchScores.IsPerfect(FormUrlEncodedMatcher.IsMatch(contentType.MediaType))) + if (FormUrlEncodedMatcher.IsMatch(contentType.MediaType).IsPerfect()) { return BodyType.FormUrlEncoded; } - if (TextContentTypeMatchers.Any(matcher => MatchScores.IsPerfect(matcher.IsMatch(contentType.MediaType)))) + if (TextContentTypeMatchers.Any(matcher => matcher.IsMatch(contentType.MediaType).IsPerfect())) { return BodyType.String; } - if (JsonContentTypesMatchers.Any(matcher => MatchScores.IsPerfect(matcher.IsMatch(contentType.MediaType)))) + if (JsonContentTypesMatchers.Any(matcher => matcher.IsMatch(contentType.MediaType).IsPerfect())) { return BodyType.Json; } - if (MultipartContentTypesMatchers.Any(matcher => MatchScores.IsPerfect(matcher.IsMatch(contentType.MediaType)))) + if (MultipartContentTypesMatchers.Any(matcher => matcher.IsMatch(contentType.MediaType).IsPerfect())) { return BodyType.MultiPart; } diff --git a/src/WireMock.Net/Util/MimeKitUtils.cs b/src/WireMock.Net/Util/MimeKitUtils.cs index ca62465c..37eac472 100644 --- a/src/WireMock.Net/Util/MimeKitUtils.cs +++ b/src/WireMock.Net/Util/MimeKitUtils.cs @@ -1,8 +1,11 @@ #if MIMEKIT using System; +using System.Diagnostics.CodeAnalysis; using System.IO; +using System.Linq; using System.Text; using MimeKit; +using Stef.Validation; using WireMock.Http; using WireMock.Types; @@ -10,21 +13,31 @@ namespace WireMock.Util; internal static class MimeKitUtils { - public static MimeMessage GetMimeMessage(IBodyData? bodyData, string contentTypeHeaderValue) + public static bool TryGetMimeMessage(IRequestMessage requestMessage, [NotNullWhen(true)] out MimeMessage? mimeMessage) { - var bytes = bodyData?.DetectedBodyType switch + Guard.NotNull(requestMessage); + + if (requestMessage.BodyData != null && requestMessage.Headers?.TryGetValue(HttpKnownHeaderNames.ContentType, out var contentTypeHeader) == true && contentTypeHeader.Any()) { - // If the body is bytes, use the BodyAsBytes to match on. - BodyType.Bytes => bodyData.BodyAsBytes!, + var bytes = requestMessage.BodyData?.DetectedBodyType switch + { + // If the body is bytes, use the BodyAsBytes to match on. + BodyType.Bytes => requestMessage.BodyData.BodyAsBytes!, - // If the body is a String or MultiPart, use the BodyAsString to match on. - BodyType.String or BodyType.MultiPart => Encoding.UTF8.GetBytes(bodyData.BodyAsString!), + // If the body is a String or MultiPart, use the BodyAsString to match on. + BodyType.String or BodyType.MultiPart => Encoding.UTF8.GetBytes(requestMessage.BodyData.BodyAsString!), - _ => throw new NotSupportedException() - }; + _ => throw new NotSupportedException() + }; - var fixedBytes = FixBytes(bytes, contentTypeHeaderValue); - return MimeMessage.Load(new MemoryStream(fixedBytes)); + var fixedBytes = FixBytes(bytes, contentTypeHeader[0]); + + mimeMessage = MimeMessage.Load(new MemoryStream(fixedBytes)); + return true; + } + + mimeMessage = null; + return false; } private static byte[] FixBytes(byte[] bytes, WireMockList contentType) diff --git a/test/WireMock.Net.Tests/Matchers/CSharpCodeMatcherTests.cs b/test/WireMock.Net.Tests/Matchers/CSharpCodeMatcherTests.cs index 26fcc3ac..fb7466ce 100644 --- a/test/WireMock.Net.Tests/Matchers/CSharpCodeMatcherTests.cs +++ b/test/WireMock.Net.Tests/Matchers/CSharpCodeMatcherTests.cs @@ -1,3 +1,4 @@ +using FluentAssertions; using NFluent; using WireMock.Matchers; using Xunit; @@ -11,12 +12,13 @@ public class CSharpCodeMatcherTests { // Assign string input = "x"; - - // Act var matcher = new CSharpCodeMatcher("return it == \"x\";"); + // Act + var score = matcher.IsMatch(input).Score; + // Assert - Check.That(matcher.IsMatch(input)).IsEqualTo(1.0d); + score.Should().Be(MatchScores.Perfect); } [Fact] @@ -24,12 +26,13 @@ public class CSharpCodeMatcherTests { // Assign string input = "y"; - - // Act var matcher = new CSharpCodeMatcher("return it == \"x\";"); + // Act + var score = matcher.IsMatch(input).Score; + // Assert - Check.That(matcher.IsMatch(input)).IsEqualTo(0.0d); + score.Should().Be(MatchScores.Mismatch); } [Fact] @@ -37,12 +40,13 @@ public class CSharpCodeMatcherTests { // Assign string input = "x"; - - // Act var matcher = new CSharpCodeMatcher(MatchBehaviour.RejectOnMatch, MatchOperator.Or, "return it == \"x\";"); + // Act + var score = matcher.IsMatch(input).Score; + // Assert - Check.That(matcher.IsMatch(input)).IsEqualTo(0.0d); + score.Should().Be(MatchScores.Mismatch); } [Fact] @@ -55,12 +59,13 @@ public class CSharpCodeMatcherTests Name = "Test" }; - // Act var matcher = new CSharpCodeMatcher("return it.Id > 1 && it.Name == \"Test\";"); - double match = matcher.IsMatch(input); + + // Act + var score = matcher.IsMatch(input).Score; // Assert - Assert.Equal(1.0, match); + score.Should().Be(MatchScores.Perfect); } [Fact] diff --git a/test/WireMock.Net.Tests/Matchers/ContentTypeMatcherTests.cs b/test/WireMock.Net.Tests/Matchers/ContentTypeMatcherTests.cs index 3bec9227..1f27964c 100644 --- a/test/WireMock.Net.Tests/Matchers/ContentTypeMatcherTests.cs +++ b/test/WireMock.Net.Tests/Matchers/ContentTypeMatcherTests.cs @@ -1,3 +1,4 @@ +using FluentAssertions; using NFluent; using WireMock.Matchers; using Xunit; @@ -14,7 +15,12 @@ public class ContentTypeMatcherTests public void ContentTypeMatcher_IsMatchWithIgnoreCaseFalse_Positive(string contentType) { var matcher = new ContentTypeMatcher("application/json"); - Check.That(matcher.IsMatch(contentType)).IsEqualTo(1.0d); + + // Act + var score = matcher.IsMatch(contentType).Score; + + // Assert + score.Should().Be(MatchScores.Perfect); } [Theory] @@ -26,7 +32,12 @@ public class ContentTypeMatcherTests public void ContentTypeMatcher_IsMatchWithIgnoreCaseTrue_Positive(string contentType) { var matcher = new ContentTypeMatcher("application/json", true); - Check.That(matcher.IsMatch(contentType)).IsEqualTo(1.0d); + + // Act + var score = matcher.IsMatch(contentType).Score; + + // Assert + score.Should().Be(MatchScores.Perfect); } [Fact] diff --git a/test/WireMock.Net.Tests/Matchers/ExactMatcherTests.cs b/test/WireMock.Net.Tests/Matchers/ExactMatcherTests.cs index 2a6d1e68..38efb345 100644 --- a/test/WireMock.Net.Tests/Matchers/ExactMatcherTests.cs +++ b/test/WireMock.Net.Tests/Matchers/ExactMatcherTests.cs @@ -39,7 +39,7 @@ public class ExactMatcherTests var matcher = new ExactMatcher(true, "x"); // Act - double result = matcher.IsMatch("X"); + double result = matcher.IsMatch("X").Score; // Assert Check.That(result).IsEqualTo(1.0); @@ -52,7 +52,7 @@ public class ExactMatcherTests var matcher = new ExactMatcher("x"); // Act - double result = matcher.IsMatch("x"); + double result = matcher.IsMatch("x").Score; // Assert Check.That(result).IsEqualTo(1.0); @@ -65,7 +65,7 @@ public class ExactMatcherTests var matcher = new ExactMatcher("x"); // Act - double result = matcher.IsMatch("y"); + double result = matcher.IsMatch("y").Score; // Assert Check.That(result).IsEqualTo(0.0); @@ -78,7 +78,7 @@ public class ExactMatcherTests var matcher = new ExactMatcher("x", "y"); // Act - double result = matcher.IsMatch("x"); + double result = matcher.IsMatch("x").Score; // Assert Check.That(result).IsEqualTo(1.0); @@ -91,7 +91,7 @@ public class ExactMatcherTests var matcher = new ExactMatcher("x", "y"); // Act - double result = matcher.IsMatch("x"); + double result = matcher.IsMatch("x").Score; // Assert Check.That(result).IsEqualTo(1.0); @@ -104,10 +104,10 @@ public class ExactMatcherTests public void ExactMatcher_IsMatch_WithMultiplePatterns_Average_ReturnsMatch(MatchOperator matchOperator, double score) { // Assign - var matcher = new ExactMatcher(MatchBehaviour.AcceptOnMatch, false, false, matchOperator, "x", "y"); + var matcher = new ExactMatcher(MatchBehaviour.AcceptOnMatch, false, matchOperator, "x", "y"); // Act - double result = matcher.IsMatch("x"); + double result = matcher.IsMatch("x").Score; // Assert Check.That(result).IsEqualTo(score); @@ -120,7 +120,7 @@ public class ExactMatcherTests var matcher = new ExactMatcher("cat"); // Act - double result = matcher.IsMatch("caR"); + double result = matcher.IsMatch("caR").Score; // Assert Check.That(result).IsEqualTo(0.0); @@ -130,10 +130,10 @@ public class ExactMatcherTests public void ExactMatcher_IsMatch_SinglePattern_AcceptOnMatch() { // Assign - var matcher = new ExactMatcher(MatchBehaviour.AcceptOnMatch, false, false, MatchOperator.Or, "cat"); + var matcher = new ExactMatcher(MatchBehaviour.AcceptOnMatch, false, MatchOperator.Or, "cat"); // Act - double result = matcher.IsMatch("cat"); + double result = matcher.IsMatch("cat").Score; // Assert Check.That(result).IsEqualTo(1.0); @@ -143,10 +143,10 @@ public class ExactMatcherTests public void ExactMatcher_IsMatch_SinglePattern_RejectOnMatch() { // Assign - var matcher = new ExactMatcher(MatchBehaviour.RejectOnMatch, false, false, MatchOperator.Or, "cat"); + var matcher = new ExactMatcher(MatchBehaviour.RejectOnMatch, false, MatchOperator.Or, "cat"); // Act - double result = matcher.IsMatch("cat"); + double result = matcher.IsMatch("cat").Score; // Assert Check.That(result).IsEqualTo(0.0); diff --git a/test/WireMock.Net.Tests/Matchers/ExactObjectMatcherTests.cs b/test/WireMock.Net.Tests/Matchers/ExactObjectMatcherTests.cs index 222e3e77..6bb9eaaf 100644 --- a/test/WireMock.Net.Tests/Matchers/ExactObjectMatcherTests.cs +++ b/test/WireMock.Net.Tests/Matchers/ExactObjectMatcherTests.cs @@ -14,7 +14,7 @@ public class ExactObjectMatcherTests // Act var matcher = new ExactObjectMatcher(obj); - string name = matcher.Name; + var name = matcher.Name; // Assert Check.That(name).Equals("ExactObjectMatcher"); @@ -28,10 +28,10 @@ public class ExactObjectMatcherTests // Act var matcher = new ExactObjectMatcher(new byte[] { 1, 2 }); - double result = matcher.IsMatch(checkValue); + var score = matcher.IsMatch(checkValue).Score; // Assert - Check.That(result).IsEqualTo(1.0); + Check.That(score).IsEqualTo(1.0); } [Fact] @@ -42,10 +42,10 @@ public class ExactObjectMatcherTests // Act var matcher = new ExactObjectMatcher(obj); - double result = matcher.IsMatch(new { x = 500, s = "s" }); + var score = matcher.IsMatch(new { x = 500, s = "s" }).Score; // Assert - Check.That(result).IsEqualTo(1.0); + Check.That(score).IsEqualTo(1.0); } [Fact] @@ -56,9 +56,9 @@ public class ExactObjectMatcherTests // Act var matcher = new ExactObjectMatcher(MatchBehaviour.RejectOnMatch, obj); - double result = matcher.IsMatch(new { x = 500, s = "s" }); + var score = matcher.IsMatch(new { x = 500, s = "s" }).Score; // Assert - Check.That(result).IsEqualTo(0.0); + Check.That(score).IsEqualTo(0.0); } } \ No newline at end of file diff --git a/test/WireMock.Net.Tests/Matchers/GraphQLMatcherTests.cs b/test/WireMock.Net.Tests/Matchers/GraphQLMatcherTests.cs index c83b6249..cad8de3f 100644 --- a/test/WireMock.Net.Tests/Matchers/GraphQLMatcherTests.cs +++ b/test/WireMock.Net.Tests/Matchers/GraphQLMatcherTests.cs @@ -51,7 +51,7 @@ public class GraphQLMatcherTests var result = matcher.IsMatch(input); // Assert - result.Should().Be(MatchScores.Perfect); + result.Score.Should().Be(MatchScores.Perfect); matcher.GetPatterns().Should().Contain(TestSchema); } @@ -71,7 +71,7 @@ public class GraphQLMatcherTests var result = matcher.IsMatch(input); // Assert - result.Should().Be(MatchScores.Perfect); + result.Score.Should().Be(MatchScores.Perfect); matcher.GetPatterns().Should().Contain(TestSchema); } @@ -93,7 +93,7 @@ public class GraphQLMatcherTests var result = matcher.IsMatch(input); // Assert - result.Should().Be(MatchScores.Mismatch); + result.Score.Should().Be(MatchScores.Mismatch); } [Fact] @@ -111,21 +111,22 @@ public class GraphQLMatcherTests var result = matcher.IsMatch(input); // Assert - result.Should().Be(MatchScores.Perfect); + result.Score.Should().Be(MatchScores.Perfect); } [Fact] - public void GraphQLMatcher_For_ValidSchema_And_IncorrectQueryWithError_WithThrowExceptionTrue_ThrowsException() + public void GraphQLMatcher_For_ValidSchema_And_IncorrectQueryWithError_WithThrowExceptionTrue_ReturnsError() { // Arrange var input = "{\"query\":\"{\\r\\n studentsX {\\r\\n fullName\\r\\n X\\r\\n }\\r\\n}\"}"; // Act - var matcher = new GraphQLMatcher(TestSchema, MatchBehaviour.AcceptOnMatch, true); - Action action = () => matcher.IsMatch(input); + var matcher = new GraphQLMatcher(TestSchema); + var result = matcher.IsMatch(input); // Assert - action.Should().Throw(); + result.Score.Should().Be(MatchScores.Mismatch); + result.Exception!.Message.Should().StartWith("Cannot query field 'studentsX' on type 'Query'"); } [Fact] diff --git a/test/WireMock.Net.Tests/Matchers/JmesPathMatcherTests.cs b/test/WireMock.Net.Tests/Matchers/JmesPathMatcherTests.cs index 05d42d5e..fc8890cb 100644 --- a/test/WireMock.Net.Tests/Matchers/JmesPathMatcherTests.cs +++ b/test/WireMock.Net.Tests/Matchers/JmesPathMatcherTests.cs @@ -42,7 +42,7 @@ public class JmesPathMatcherTests var matcher = new JmesPathMatcher(""); // Act - double match = matcher.IsMatch(bytes); + double match = matcher.IsMatch(bytes).Score; // Assert Check.That(match).IsEqualTo(0); @@ -56,7 +56,7 @@ public class JmesPathMatcherTests var matcher = new JmesPathMatcher(""); // Act - double match = matcher.IsMatch(s); + double match = matcher.IsMatch(s).Score; // Assert Check.That(match).IsEqualTo(0); @@ -70,7 +70,7 @@ public class JmesPathMatcherTests var matcher = new JmesPathMatcher(""); // Act - double match = matcher.IsMatch(o); + double match = matcher.IsMatch(o).Score; // Assert Check.That(match).IsEqualTo(0); @@ -83,7 +83,7 @@ public class JmesPathMatcherTests var matcher = new JmesPathMatcher("xxx"); // Act - double match = matcher.IsMatch(""); + double match = matcher.IsMatch("").Score; // Assert Check.That(match).IsEqualTo(0); @@ -96,7 +96,7 @@ public class JmesPathMatcherTests var matcher = new JmesPathMatcher(""); // Act - double match = matcher.IsMatch("x"); + double match = matcher.IsMatch("x").Score; // Assert Check.That(match).IsEqualTo(0); @@ -109,7 +109,7 @@ public class JmesPathMatcherTests var matcher = new JmesPathMatcher("things.name == 'RequiredThing'"); // Act - double match = matcher.IsMatch(new { things = new { name = "RequiredThing" } }); + double match = matcher.IsMatch(new { things = new { name = "RequiredThing" } }).Score; // Assert Check.That(match).IsEqualTo(1); @@ -132,7 +132,7 @@ public class JmesPathMatcherTests { "Id", new JValue(1) }, { "things", sub } }; - double match = matcher.IsMatch(jobject); + double match = matcher.IsMatch(jobject).Score; // Assert Check.That(match).IsEqualTo(1); @@ -145,7 +145,7 @@ public class JmesPathMatcherTests var matcher = new JmesPathMatcher("things.x == 'RequiredThing'"); // Act - double match = matcher.IsMatch(JObject.Parse("{ \"things\": { \"x\": \"RequiredThing\" } }")); + double match = matcher.IsMatch(JObject.Parse("{ \"things\": { \"x\": \"RequiredThing\" } }")).Score; // Assert Check.That(match).IsEqualTo(1); @@ -155,10 +155,10 @@ public class JmesPathMatcherTests public void JmesPathMatcher_IsMatch_RejectOnMatch() { // Assign - var matcher = new JmesPathMatcher(MatchBehaviour.RejectOnMatch, false, MatchOperator.Or, "things.x == 'RequiredThing'"); + var matcher = new JmesPathMatcher(MatchBehaviour.RejectOnMatch, MatchOperator.Or, "things.x == 'RequiredThing'"); // Act - double match = matcher.IsMatch(JObject.Parse("{ \"things\": { \"x\": \"RequiredThing\" } }")); + double match = matcher.IsMatch(JObject.Parse("{ \"things\": { \"x\": \"RequiredThing\" } }")).Score; // Assert Check.That(match).IsEqualTo(0.0); diff --git a/test/WireMock.Net.Tests/Matchers/JsonMatcherTests.cs b/test/WireMock.Net.Tests/Matchers/JsonMatcherTests.cs index 9b38fff0..266c590b 100644 --- a/test/WireMock.Net.Tests/Matchers/JsonMatcherTests.cs +++ b/test/WireMock.Net.Tests/Matchers/JsonMatcherTests.cs @@ -82,29 +82,17 @@ public class JsonMatcherTests } [Fact] - public void JsonMatcher_IsMatch_WithInvalidValue_And_ThrowExceptionIsFalse_Should_ReturnMismatch() + public void JsonMatcher_IsMatch_WithInvalidValue_Should_ReturnMismatch_And_Exception_ShouldBeSet() { // Assign var matcher = new JsonMatcher(""); // Act - double match = matcher.IsMatch(new MemoryStream()); + var result = matcher.IsMatch(new MemoryStream()); // Assert - Check.That(match).IsEqualTo(0); - } - - [Fact] - public void JsonMatcher_IsMatch_WithInvalidValue_And_ThrowExceptionIsTrue_Should_ReturnMismatch() - { - // Assign - var matcher = new JsonMatcher("", false, true); - - // Act - Action action = () => matcher.IsMatch(new MemoryStream()); - - // Assert - action.Should().Throw(); + result.Score.Should().Be(MatchScores.Mismatch); + result.Exception.Should().BeAssignableTo(); } [Fact] @@ -115,7 +103,7 @@ public class JsonMatcherTests var matcher = new JsonMatcher(""); // Act - double match = matcher.IsMatch(bytes); + double match = matcher.IsMatch(bytes).Score; // Assert Check.That(match).IsEqualTo(0); @@ -129,7 +117,7 @@ public class JsonMatcherTests var matcher = new JsonMatcher(""); // Act - double match = matcher.IsMatch(s); + double match = matcher.IsMatch(s).Score; // Assert Check.That(match).IsEqualTo(0); @@ -143,7 +131,7 @@ public class JsonMatcherTests var matcher = new JsonMatcher(""); // Act - double match = matcher.IsMatch(o); + double match = matcher.IsMatch(o).Score; // Assert Check.That(match).IsEqualTo(0); @@ -161,7 +149,7 @@ public class JsonMatcherTests "x", "y" }; - double match = matcher.IsMatch(jArray); + double match = matcher.IsMatch(jArray).Score; // Assert Assert.Equal(1.0, match); @@ -179,7 +167,7 @@ public class JsonMatcherTests { "Id", new JValue(1) }, { "Name", new JValue("Test") } }; - double match = matcher.IsMatch(jObject); + double match = matcher.IsMatch(jObject).Score; // Assert Assert.Equal(1.0, match); @@ -197,7 +185,7 @@ public class JsonMatcherTests { "Id", new JValue(1) }, { "NaMe", new JValue("Test") } }; - double match = matcher.IsMatch(jObject); + double match = matcher.IsMatch(jObject).Score; // Assert Assert.Equal(1.0, match); @@ -211,7 +199,7 @@ public class JsonMatcherTests // Act var jObject = JObject.Parse("{ \"Id\" : 1, \"Name\" : \"Test\" }"); - double match = matcher.IsMatch(jObject); + double match = matcher.IsMatch(jObject).Score; // Assert Assert.Equal(1.0, match); @@ -225,7 +213,7 @@ public class JsonMatcherTests // Act var jObject = JObject.Parse("{ \"Id\" : 1, \"Name\" : \"Test\" }"); - double match = matcher.IsMatch(jObject); + double match = matcher.IsMatch(jObject).Score; // Assert Assert.Equal(1.0, match); @@ -243,7 +231,7 @@ public class JsonMatcherTests "x", "y" }; - double match = matcher.IsMatch(jArray); + double match = matcher.IsMatch(jArray).Score; // Assert Assert.Equal(1.0, match); @@ -261,7 +249,7 @@ public class JsonMatcherTests { "Id", new JValue(1) }, { "Name", new JValue("Test") } }; - double match = matcher.IsMatch(jObject); + double match = matcher.IsMatch(jObject).Score; // Assert Assert.Equal(1.0, match); @@ -279,7 +267,7 @@ public class JsonMatcherTests { "Id", new JValue(1) }, { "Name", new JValue("Test") } }; - double match = matcher.IsMatch(jObject); + double match = matcher.IsMatch(jObject).Score; // Assert Assert.Equal(1.0, match); @@ -297,7 +285,7 @@ public class JsonMatcherTests { "Id", new JValue(1) }, { "Name", new JValue("Test") } }; - double match = matcher.IsMatch(jObject); + double match = matcher.IsMatch(jObject).Score; // Assert Assert.Equal(0.0, match); @@ -314,7 +302,7 @@ public class JsonMatcherTests { { "preferredAt", new JValue("2019-11-21T10:32:53.2210009+00:00") } }; - double match = matcher.IsMatch(jObject); + double match = matcher.IsMatch(jObject).Score; // Assert Assert.Equal(1.0, match); @@ -331,7 +319,7 @@ public class JsonMatcherTests { { "NormalEnum", new JValue(0) } }; - double match = matcher.IsMatch(jObject); + double match = matcher.IsMatch(jObject).Score; // Assert match.Should().Be(1.0); @@ -348,7 +336,7 @@ public class JsonMatcherTests { { "EnumWithJsonConverter", new JValue("Type1") } }; - double match = matcher.IsMatch(jObject); + double match = matcher.IsMatch(jObject).Score; // Assert match.Should().Be(1.0); diff --git a/test/WireMock.Net.Tests/Matchers/JsonPartialMatcherTests.cs b/test/WireMock.Net.Tests/Matchers/JsonPartialMatcherTests.cs index 3a2d3043..01b610b1 100644 --- a/test/WireMock.Net.Tests/Matchers/JsonPartialMatcherTests.cs +++ b/test/WireMock.Net.Tests/Matchers/JsonPartialMatcherTests.cs @@ -60,29 +60,17 @@ public class JsonPartialMatcherTests } [Fact] - public void JsonPartialMatcher_IsMatch_WithInvalidValue_And_ThrowExceptionIsFalse_Should_ReturnMismatch() + public void JsonPartialMatcher_IsMatch_WithInvalidValue_Should_ReturnMismatch_And_Exception_ShouldBeSet() { // Assign var matcher = new JsonPartialMatcher(""); // Act - double match = matcher.IsMatch(new MemoryStream()); + var result = matcher.IsMatch(new MemoryStream()); // Assert - Check.That(match).IsEqualTo(0); - } - - [Fact] - public void JsonPartialMatcher_IsMatch_WithInvalidValue_And_ThrowExceptionIsTrue_Should_ReturnMismatch() - { - // Assign - var matcher = new JsonPartialMatcher("", false, true); - - // Act - Action action = () => matcher.IsMatch(new MemoryStream()); - - // Assert - action.Should().Throw(); + result.Score.Should().Be(MatchScores.Mismatch); + result.Exception.Should().BeAssignableTo(); } [Fact] @@ -93,7 +81,7 @@ public class JsonPartialMatcherTests var matcher = new JsonPartialMatcher(""); // Act - double match = matcher.IsMatch(bytes); + double match = matcher.IsMatch(bytes).Score; // Assert Check.That(match).IsEqualTo(0); @@ -107,7 +95,7 @@ public class JsonPartialMatcherTests var matcher = new JsonPartialMatcher(""); // Act - double match = matcher.IsMatch(s); + double match = matcher.IsMatch(s).Score; // Assert Check.That(match).IsEqualTo(0); @@ -121,7 +109,7 @@ public class JsonPartialMatcherTests var matcher = new JsonPartialMatcher(""); // Act - double match = matcher.IsMatch(o); + double match = matcher.IsMatch(o).Score; // Assert Check.That(match).IsEqualTo(0); @@ -139,7 +127,7 @@ public class JsonPartialMatcherTests "x", "y" }; - double match = matcher.IsMatch(jArray); + double match = matcher.IsMatch(jArray).Score; // Assert Assert.Equal(1.0, match); @@ -157,7 +145,7 @@ public class JsonPartialMatcherTests { "Id", new JValue(1) }, { "Name", new JValue("Test") } }; - double match = matcher.IsMatch(jObject); + double match = matcher.IsMatch(jObject).Score; // Assert Assert.Equal(1.0, match); @@ -167,7 +155,7 @@ public class JsonPartialMatcherTests public void JsonPartialMatcher_IsMatch_WithRegexTrue() { // Assign - var matcher = new JsonPartialMatcher(new { Id = "^\\d+$", Name = "Test" }, false, false, true); + var matcher = new JsonPartialMatcher(new { Id = "^\\d+$", Name = "Test" }, false, true); // Act var jObject = new JObject @@ -175,7 +163,7 @@ public class JsonPartialMatcherTests { "Id", new JValue(1) }, { "Name", new JValue("Test") } }; - double match = matcher.IsMatch(jObject); + double match = matcher.IsMatch(jObject).Score; // Assert Assert.Equal(1.0, match); @@ -193,7 +181,7 @@ public class JsonPartialMatcherTests { "Id", new JValue(1) }, { "Name", new JValue("Test") } }; - double match = matcher.IsMatch(jObject); + double match = matcher.IsMatch(jObject).Score; // Assert Assert.Equal(0.0, match); @@ -203,10 +191,11 @@ public class JsonPartialMatcherTests public void JsonPartialMatcher_IsMatch_GuidAsString_UsingRegex() { var guid = new Guid("1111238e-b775-44a9-a263-95e570135c94"); - var matcher = new JsonPartialMatcher(new { + var matcher = new JsonPartialMatcher(new + { Id = 1, Name = "^1111[a-fA-F0-9]{4}(-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}$" - }, false, false, true); + }, false, true); // Act var jObject = new JObject @@ -214,7 +203,7 @@ public class JsonPartialMatcherTests { "Id", new JValue(1) }, { "Name", new JValue(guid) } }; - double match = matcher.IsMatch(jObject); + double match = matcher.IsMatch(jObject).Score; // Assert Assert.Equal(1.0, match); @@ -232,7 +221,7 @@ public class JsonPartialMatcherTests { "Id", new JValue(1) }, { "NaMe", new JValue("Test") } }; - double match = matcher.IsMatch(jObject); + double match = matcher.IsMatch(jObject).Score; // Assert Assert.Equal(1.0, match); @@ -246,7 +235,7 @@ public class JsonPartialMatcherTests // Act var jObject = JObject.Parse("{ \"Id\" : 1, \"Name\" : \"Test\" }"); - double match = matcher.IsMatch(jObject); + double match = matcher.IsMatch(jObject).Score; // Assert Assert.Equal(1.0, match); @@ -260,7 +249,7 @@ public class JsonPartialMatcherTests // Act var jObject = JObject.Parse("{ \"Id\" : 1, \"Name\" : \"Test\" }"); - double match = matcher.IsMatch(jObject); + double match = matcher.IsMatch(jObject).Score; // Assert Assert.Equal(1.0, match); @@ -278,7 +267,7 @@ public class JsonPartialMatcherTests "x", "y" }; - double match = matcher.IsMatch(jArray); + double match = matcher.IsMatch(jArray).Score; // Assert Assert.Equal(1.0, match); @@ -296,7 +285,7 @@ public class JsonPartialMatcherTests { "Id", new JValue(1) }, { "Name", new JValue("Test") } }; - double match = matcher.IsMatch(jObject); + double match = matcher.IsMatch(jObject).Score; // Assert Assert.Equal(1.0, match); @@ -305,20 +294,20 @@ public class JsonPartialMatcherTests [Fact] public void JsonPartialMatcher_IsMatch_GuidAsString() { - // Assign - var guid = Guid.NewGuid(); - var matcher = new JsonPartialMatcher(new { Id = 1, Name = guid }); + // Assign + var guid = Guid.NewGuid(); + var matcher = new JsonPartialMatcher(new { Id = 1, Name = guid }); - // Act - var jObject = new JObject - { - { "Id", new JValue(1) }, - { "Name", new JValue(guid.ToString()) } - }; - double match = matcher.IsMatch(jObject); + // Act + var jObject = new JObject + { + { "Id", new JValue(1) }, + { "Name", new JValue(guid.ToString()) } + }; + double match = matcher.IsMatch(jObject).Score; - // Assert - Assert.Equal(1.0, match); + // Assert + Assert.Equal(1.0, match); } [Fact] @@ -333,7 +322,7 @@ public class JsonPartialMatcherTests { "Id", new JValue(1) }, { "Name", new JValue("Test") } }; - double match = matcher.IsMatch(jObject); + double match = matcher.IsMatch(jObject).Score; // Assert Assert.Equal(1.0, match); @@ -351,7 +340,7 @@ public class JsonPartialMatcherTests { "Id", new JValue(1) }, { "Name", new JValue("Test") } }; - double match = matcher.IsMatch(jObject); + double match = matcher.IsMatch(jObject).Score; // Assert Assert.Equal(0.0, match); @@ -368,7 +357,7 @@ public class JsonPartialMatcherTests { { "preferredAt", new JValue("2019-11-21T10:32:53.2210009+00:00") } }; - double match = matcher.IsMatch(jObject); + double match = matcher.IsMatch(jObject).Score; // Assert Assert.Equal(1.0, match); @@ -391,7 +380,7 @@ public class JsonPartialMatcherTests var matcher = new JsonPartialMatcher(value); // Act - double match = matcher.IsMatch(input); + double match = matcher.IsMatch(input).Score; // Assert Assert.Equal(1.0, match); @@ -415,7 +404,7 @@ public class JsonPartialMatcherTests var matcher = new JsonPartialMatcher(value); // Act - double match = matcher.IsMatch(input); + double match = matcher.IsMatch(input).Score; // Assert Assert.Equal(0.0, match); @@ -434,7 +423,7 @@ public class JsonPartialMatcherTests var matcher = new JsonPartialMatcher(value); // Act - double match = matcher.IsMatch(input); + double match = matcher.IsMatch(input).Score; // Assert Assert.Equal(1.0, match); @@ -453,7 +442,7 @@ public class JsonPartialMatcherTests var matcher = new JsonPartialMatcher(value); // Act - double match = matcher.IsMatch(input); + double match = matcher.IsMatch(input).Score; // Assert Assert.Equal(0.0, match); diff --git a/test/WireMock.Net.Tests/Matchers/JsonPartialWildcardMatcherTests.cs b/test/WireMock.Net.Tests/Matchers/JsonPartialWildcardMatcherTests.cs index 77ce09c8..b89b3011 100644 --- a/test/WireMock.Net.Tests/Matchers/JsonPartialWildcardMatcherTests.cs +++ b/test/WireMock.Net.Tests/Matchers/JsonPartialWildcardMatcherTests.cs @@ -60,29 +60,17 @@ public class JsonPartialWildcardMatcherTests } [Fact] - public void JsonPartialWildcardMatcher_IsMatch_WithInvalidValue_And_ThrowExceptionIsFalse_Should_ReturnMismatch() + public void JsonPartialWildcardMatcher_IsMatch_WithInvalidValue_Should_ReturnMismatch_And_Exception_ShouldBeSet() { // Assign var matcher = new JsonPartialWildcardMatcher(""); // Act - double match = matcher.IsMatch(new MemoryStream()); + var result = matcher.IsMatch(new MemoryStream()); // Assert - Check.That(match).IsEqualTo(0); - } - - [Fact] - public void JsonPartialWildcardMatcher_IsMatch_WithInvalidValue_And_ThrowExceptionIsTrue_Should_ReturnMismatch() - { - // Assign - var matcher = new JsonPartialWildcardMatcher("", false, true); - - // Act - Action action = () => matcher.IsMatch(new MemoryStream()); - - // Assert - action.Should().Throw(); + result.Score.Should().Be(MatchScores.Mismatch); + result.Exception.Should().BeAssignableTo(); } [Fact] @@ -93,7 +81,7 @@ public class JsonPartialWildcardMatcherTests var matcher = new JsonPartialWildcardMatcher(""); // Act - double match = matcher.IsMatch(bytes); + double match = matcher.IsMatch(bytes).Score; // Assert Check.That(match).IsEqualTo(0); @@ -107,7 +95,7 @@ public class JsonPartialWildcardMatcherTests var matcher = new JsonPartialWildcardMatcher(""); // Act - double match = matcher.IsMatch(s); + double match = matcher.IsMatch(s).Score; // Assert Check.That(match).IsEqualTo(0); @@ -121,7 +109,7 @@ public class JsonPartialWildcardMatcherTests var matcher = new JsonPartialWildcardMatcher(""); // Act - double match = matcher.IsMatch(o); + double match = matcher.IsMatch(o).Score; // Assert Check.That(match).IsEqualTo(0); @@ -139,7 +127,7 @@ public class JsonPartialWildcardMatcherTests "x", "y" }; - double match = matcher.IsMatch(jArray); + double match = matcher.IsMatch(jArray).Score; // Assert Assert.Equal(1.0, match); @@ -157,7 +145,7 @@ public class JsonPartialWildcardMatcherTests { "Id", new JValue(1) }, { "Name", new JValue("Test") } }; - double match = matcher.IsMatch(jObject); + double match = matcher.IsMatch(jObject).Score; // Assert Assert.Equal(1.0, match); @@ -175,7 +163,7 @@ public class JsonPartialWildcardMatcherTests { "Id", new JValue(1) }, { "NaMe", new JValue("Test") } }; - double match = matcher.IsMatch(jObject); + double match = matcher.IsMatch(jObject).Score; // Assert Assert.Equal(1.0, match); @@ -189,7 +177,7 @@ public class JsonPartialWildcardMatcherTests // Act var jObject = JObject.Parse("{ \"Id\" : 1, \"Name\" : \"Test\" }"); - double match = matcher.IsMatch(jObject); + double match = matcher.IsMatch(jObject).Score; // Assert Assert.Equal(1.0, match); @@ -203,7 +191,7 @@ public class JsonPartialWildcardMatcherTests // Act var jObject = JObject.Parse("{ \"Id\" : 1, \"Name\" : \"Test\" }"); - double match = matcher.IsMatch(jObject); + double match = matcher.IsMatch(jObject).Score; // Assert Assert.Equal(1.0, match); @@ -221,7 +209,7 @@ public class JsonPartialWildcardMatcherTests "x", "y" }; - double match = matcher.IsMatch(jArray); + double match = matcher.IsMatch(jArray).Score; // Assert Assert.Equal(1.0, match); @@ -239,7 +227,7 @@ public class JsonPartialWildcardMatcherTests { "Id", new JValue(1) }, { "Name", new JValue("Test") } }; - double match = matcher.IsMatch(jObject); + double match = matcher.IsMatch(jObject).Score; // Assert Assert.Equal(1.0, match); @@ -257,7 +245,7 @@ public class JsonPartialWildcardMatcherTests { "Id", new JValue(1) }, { "Name", new JValue("Test") } }; - double match = matcher.IsMatch(jObject); + double match = matcher.IsMatch(jObject).Score; // Assert Assert.Equal(1.0, match); @@ -275,7 +263,7 @@ public class JsonPartialWildcardMatcherTests { "Id", new JValue(1) }, { "Name", new JValue("Test") } }; - double match = matcher.IsMatch(jObject); + double match = matcher.IsMatch(jObject).Score; // Assert Assert.Equal(0.0, match); @@ -292,7 +280,7 @@ public class JsonPartialWildcardMatcherTests { { "preferredAt", new JValue("2019-11-21T10:32:53.2210009+00:00") } }; - double match = matcher.IsMatch(jObject); + double match = matcher.IsMatch(jObject).Score; // Assert Assert.Equal(1.0, match); @@ -315,7 +303,7 @@ public class JsonPartialWildcardMatcherTests var matcher = new JsonPartialWildcardMatcher(value); // Act - double match = matcher.IsMatch(input); + double match = matcher.IsMatch(input).Score; // Assert Assert.Equal(1.0, match); @@ -330,7 +318,7 @@ public class JsonPartialWildcardMatcherTests var matcher = new JsonPartialWildcardMatcher(value); // Act - double match = matcher.IsMatch(input); + double match = matcher.IsMatch(input).Score; // Assert match.Should().Be(1.0); @@ -354,7 +342,7 @@ public class JsonPartialWildcardMatcherTests var matcher = new JsonPartialWildcardMatcher(value); // Act - double match = matcher.IsMatch(input); + double match = matcher.IsMatch(input).Score; // Assert Assert.Equal(0.0, match); @@ -373,7 +361,7 @@ public class JsonPartialWildcardMatcherTests var matcher = new JsonPartialWildcardMatcher(value); // Act - double match = matcher.IsMatch(input); + double match = matcher.IsMatch(input).Score; // Assert Assert.Equal(1.0, match); @@ -392,7 +380,7 @@ public class JsonPartialWildcardMatcherTests var matcher = new JsonPartialWildcardMatcher(value); // Act - double match = matcher.IsMatch(input); + double match = matcher.IsMatch(input).Score; // Assert Assert.Equal(0.0, match); diff --git a/test/WireMock.Net.Tests/Matchers/JsonPathMatcherTests.cs b/test/WireMock.Net.Tests/Matchers/JsonPathMatcherTests.cs index 33a21a28..6f71ed5b 100644 --- a/test/WireMock.Net.Tests/Matchers/JsonPathMatcherTests.cs +++ b/test/WireMock.Net.Tests/Matchers/JsonPathMatcherTests.cs @@ -42,7 +42,7 @@ public class JsonPathMatcherTests var matcher = new JsonPathMatcher(""); // Act - double match = matcher.IsMatch(bytes); + double match = matcher.IsMatch(bytes).Score; // Assert Check.That(match).IsEqualTo(0); @@ -56,7 +56,7 @@ public class JsonPathMatcherTests var matcher = new JsonPathMatcher(""); // Act - double match = matcher.IsMatch(s); + double match = matcher.IsMatch(s).Score; // Assert Check.That(match).IsEqualTo(0); @@ -70,7 +70,7 @@ public class JsonPathMatcherTests var matcher = new JsonPathMatcher(""); // Act - double match = matcher.IsMatch(o); + double match = matcher.IsMatch(o).Score; // Assert Check.That(match).IsEqualTo(0); @@ -83,7 +83,7 @@ public class JsonPathMatcherTests var matcher = new JsonPathMatcher("xxx"); // Act - double match = matcher.IsMatch(""); + double match = matcher.IsMatch("").Score; // Assert Check.That(match).IsEqualTo(0); @@ -96,7 +96,7 @@ public class JsonPathMatcherTests var matcher = new JsonPathMatcher(""); // Act - double match = matcher.IsMatch("x"); + double match = matcher.IsMatch("x").Score; // Assert Check.That(match).IsEqualTo(0); @@ -109,7 +109,7 @@ public class JsonPathMatcherTests var matcher = new JsonPathMatcher("$..[?(@.Id == 1)]"); // Act - double match = matcher.IsMatch(new { Id = 1, Name = "Test" }); + double match = matcher.IsMatch(new { Id = 1, Name = "Test" }).Score; // Assert Check.That(match).IsEqualTo(1); @@ -122,7 +122,7 @@ public class JsonPathMatcherTests var matcher = new JsonPathMatcher("$.things[?(@.name == 'x')]"); // Act - double match = matcher.IsMatch(new { things = new { name = "x" } }); + double match = matcher.IsMatch(new { things = new { name = "x" } }).Score; // Assert Check.That(match).IsEqualTo(1); @@ -136,7 +136,7 @@ public class JsonPathMatcherTests var matcher = new JsonPathMatcher("$.things[?(@.name == 'x')]"); // Act - double match = matcher.IsMatch(json); + double match = matcher.IsMatch(json).Score; // Assert Check.That(match).IsEqualTo(1); @@ -150,7 +150,7 @@ public class JsonPathMatcherTests var matcher = new JsonPathMatcher("$.things[?(@.name == 'x')]"); // Act - double match = matcher.IsMatch(json); + double match = matcher.IsMatch(json).Score; // Assert Check.That(match).IsEqualTo(0); @@ -169,7 +169,7 @@ public class JsonPathMatcherTests { "Id", new JValue(1) }, { "Name", new JValue("Test") } }; - double match = matcher.IsMatch(jobject); + double match = matcher.IsMatch(jobject).Score; // Assert Check.That(match).IsEqualTo(1); @@ -182,7 +182,7 @@ public class JsonPathMatcherTests var matcher = new JsonPathMatcher("$..[?(@.Id == 1)]"); // Act - double match = matcher.IsMatch(JObject.Parse("{\"Id\":1,\"Name\":\"Test\"}")); + double match = matcher.IsMatch(JObject.Parse("{\"Id\":1,\"Name\":\"Test\"}")).Score; // Assert Check.That(match).IsEqualTo(1); @@ -192,10 +192,10 @@ public class JsonPathMatcherTests public void JsonPathMatcher_IsMatch_RejectOnMatch() { // Arrange - var matcher = new JsonPathMatcher(MatchBehaviour.RejectOnMatch, false, MatchOperator.Or, "$..[?(@.Id == 1)]"); + var matcher = new JsonPathMatcher(MatchBehaviour.RejectOnMatch, MatchOperator.Or, "$..[?(@.Id == 1)]"); // Act - double match = matcher.IsMatch(JObject.Parse("{\"Id\":1,\"Name\":\"Test\"}")); + double match = matcher.IsMatch(JObject.Parse("{\"Id\":1,\"Name\":\"Test\"}")).Score; // Assert Check.That(match).IsEqualTo(0.0); @@ -206,7 +206,7 @@ public class JsonPathMatcherTests { // Arrange var matcher = new JsonPathMatcher("$.arr[0].line1"); - + // Act double match = matcher.IsMatch(JObject.Parse(@"{ ""name"": ""PathSelectorTest"", @@ -215,18 +215,18 @@ public class JsonPathMatcherTests ""arr"": [{ ""line1"": ""line1"", }] - }")); + }")).Score; // Assert - Check.That(match).IsEqualTo(1.0); + Check.That(match).IsEqualTo(1.0); } - + [Fact] public void JsonPathMatcher_IsMatch_ObjectMatch() { // Arrange var matcher = new JsonPathMatcher("$.test"); - + // Act double match = matcher.IsMatch(JObject.Parse(@"{ ""name"": ""PathSelectorTest"", @@ -237,10 +237,10 @@ public class JsonPathMatcherTests ""line1"": ""line1"", } ] - }")); + }")).Score; // Assert - Check.That(match).IsEqualTo(1.0); + Check.That(match).IsEqualTo(1.0); } [Fact] @@ -248,7 +248,7 @@ public class JsonPathMatcherTests { // Arrange var matcher = new JsonPathMatcher("$.test3"); - + // Act double match = matcher.IsMatch(JObject.Parse(@"{ ""name"": ""PathSelectorTest"", @@ -259,10 +259,10 @@ public class JsonPathMatcherTests ""line1"": ""line1"", } ] - }")); - + }")).Score; + // Assert - Check.That(match).IsEqualTo(0.0); + Check.That(match).IsEqualTo(0.0); } [Fact] @@ -270,35 +270,35 @@ public class JsonPathMatcherTests { // Arrange var matcher = new JsonPathMatcher("$arr[0].line1"); - + // Act double match = matcher.IsMatch(JObject.Parse(@"{ ""name"": ""PathSelectorTest"", ""test"": ""test"", ""test2"": ""test2"", ""arr"": [] - }")); + }")).Score; // Assert - Check.That(match).IsEqualTo(0.0); + Check.That(match).IsEqualTo(0.0); } - + [Fact] public void JsonPathMatcher_IsMatch_DoesntMatchNoObjectsInArray() { // Arrange var matcher = new JsonPathMatcher("$arr[2].line1"); - + // Act double match = matcher.IsMatch(JObject.Parse(@"{ ""name"": ""PathSelectorTest"", ""test"": ""test"", ""test2"": ""test2"", ""arr"": [] - }")); + }")).Score; // Assert - Check.That(match).IsEqualTo(0.0); + Check.That(match).IsEqualTo(0.0); } [Fact] @@ -306,7 +306,7 @@ public class JsonPathMatcherTests { // Arrange var matcher = new JsonPathMatcher("$.arr[0].sub[0].subline1"); - + // Act double match = matcher.IsMatch(JObject.Parse(@"{ ""name"": ""PathSelectorTest"", @@ -319,9 +319,9 @@ public class JsonPathMatcherTests ""subline1"":""subline1"" }] }] - }")); + }")).Score; // Assert - Check.That(match).IsEqualTo(1.0); + Check.That(match).IsEqualTo(1.0); } -} +} \ No newline at end of file diff --git a/test/WireMock.Net.Tests/Matchers/LinqMatcherTests.cs b/test/WireMock.Net.Tests/Matchers/LinqMatcherTests.cs index d85a8498..483ebbad 100644 --- a/test/WireMock.Net.Tests/Matchers/LinqMatcherTests.cs +++ b/test/WireMock.Net.Tests/Matchers/LinqMatcherTests.cs @@ -1,3 +1,4 @@ +using FluentAssertions; using Newtonsoft.Json.Linq; using NFluent; using WireMock.Matchers; @@ -17,7 +18,8 @@ public class LinqMatcherTests var matcher = new LinqMatcher("DateTime.Parse(it) > \"2018-08-01 13:50:00\""); // Assert - Check.That(matcher.IsMatch(input)).IsEqualTo(1.0d); + var score = matcher.IsMatch(input).Score; + score.Should().Be(MatchScores.Perfect); } [Fact] @@ -30,7 +32,8 @@ public class LinqMatcherTests var matcher = new LinqMatcher("DateTime.Parse(it) > \"2019-01-01 00:00:00\""); // Assert - Check.That(matcher.IsMatch(input)).IsEqualTo(0.0d); + var score = matcher.IsMatch(input).Score; + score.Should().Be(MatchScores.Mismatch); } [Fact] @@ -43,7 +46,8 @@ public class LinqMatcherTests var matcher = new LinqMatcher(MatchBehaviour.RejectOnMatch, "DateTime.Parse(it) > \"2018-08-01 13:50:00\""); // Assert - Check.That(matcher.IsMatch(input)).IsEqualTo(0.0d); + var score = matcher.IsMatch(input).Score; + score.Should().Be(MatchScores.Mismatch); } [Fact] @@ -58,7 +62,7 @@ public class LinqMatcherTests // Act var matcher = new LinqMatcher("Id > 1 AND Name == \"Test\""); - double match = matcher.IsMatch(input); + double match = matcher.IsMatch(input).Score; // Assert Assert.Equal(1.0, match); @@ -77,7 +81,7 @@ public class LinqMatcherTests // Act var matcher = new LinqMatcher("IntegerId > 1 AND LongId > 1 && Name == \"Test\""); - double match = matcher.IsMatch(input); + double match = matcher.IsMatch(input).Score; // Assert Assert.Equal(1.0, match); diff --git a/test/WireMock.Net.Tests/Matchers/MimePartMatcherTests.cs b/test/WireMock.Net.Tests/Matchers/MimePartMatcherTests.cs index 467e72f0..8d15be65 100644 --- a/test/WireMock.Net.Tests/Matchers/MimePartMatcherTests.cs +++ b/test/WireMock.Net.Tests/Matchers/MimePartMatcherTests.cs @@ -55,7 +55,7 @@ AAAADElEQVR4XmMQYNgAAADkAMHebX3mAAAAAElFTkSuQmCC // Assert matcher.Name.Should().Be("MimePartMatcher"); - result.Should().Be(MatchScores.Perfect); + result.Score.Should().Be(MatchScores.Perfect); } [Fact] @@ -73,7 +73,7 @@ AAAADElEQVR4XmMQYNgAAADkAMHebX3mAAAAAElFTkSuQmCC var result = matcher.IsMatch(part); // Assert - result.Should().Be(MatchScores.Perfect); + result.Score.Should().Be(MatchScores.Perfect); } [Fact] @@ -93,7 +93,7 @@ AAAADElEQVR4XmMQYNgAAADkAMHebX3mAAAAAElFTkSuQmCC var result = matcher.IsMatch(part); // Assert - result.Should().Be(MatchScores.Perfect); + result.Score.Should().Be(MatchScores.Perfect); } } #endif \ No newline at end of file diff --git a/test/WireMock.Net.Tests/Matchers/NotNullOrEmptyMatcherTests.cs b/test/WireMock.Net.Tests/Matchers/NotNullOrEmptyMatcherTests.cs index 38a8e8e5..311434c9 100644 --- a/test/WireMock.Net.Tests/Matchers/NotNullOrEmptyMatcherTests.cs +++ b/test/WireMock.Net.Tests/Matchers/NotNullOrEmptyMatcherTests.cs @@ -12,7 +12,7 @@ public class NotNullOrEmptyMatcherTests { // Act var matcher = new NotNullOrEmptyMatcher(); - string name = matcher.Name; + var name = matcher.Name; // Assert Check.That(name).Equals("NotNullOrEmptyMatcher"); @@ -26,7 +26,7 @@ public class NotNullOrEmptyMatcherTests { // Act var matcher = new NotNullOrEmptyMatcher(); - double result = matcher.IsMatch(data); + var result = matcher.IsMatch(data).Score; // Assert result.Should().Be(expected); @@ -40,7 +40,7 @@ public class NotNullOrEmptyMatcherTests { // Act var matcher = new NotNullOrEmptyMatcher(); - double result = matcher.IsMatch(@string); + var result = matcher.IsMatch(@string).Score; // Assert result.Should().Be(expected); @@ -54,7 +54,7 @@ public class NotNullOrEmptyMatcherTests { // Act var matcher = new NotNullOrEmptyMatcher(); - double result = matcher.IsMatch((object)@string); + var result = matcher.IsMatch((object)@string).Score; // Assert result.Should().Be(expected); @@ -65,7 +65,7 @@ public class NotNullOrEmptyMatcherTests { // Act var matcher = new NotNullOrEmptyMatcher(); - double result = matcher.IsMatch(new { x = "x" }); + var result = matcher.IsMatch(new { x = "x" }).Score; // Assert result.Should().Be(1.0); diff --git a/test/WireMock.Net.Tests/Matchers/RegexMatcherTests.cs b/test/WireMock.Net.Tests/Matchers/RegexMatcherTests.cs index 552dbc68..0726e2ea 100644 --- a/test/WireMock.Net.Tests/Matchers/RegexMatcherTests.cs +++ b/test/WireMock.Net.Tests/Matchers/RegexMatcherTests.cs @@ -53,7 +53,7 @@ public class RegexMatcherTests var matcher = new RegexMatcher("H.*o"); // Act - double result = matcher.IsMatch("Hello world!"); + double result = matcher.IsMatch("Hello world!").Score; // Assert Check.That(result).IsEqualTo(1.0d); @@ -66,7 +66,7 @@ public class RegexMatcherTests var matcher = new RegexMatcher("H.*o"); // Act - double result = matcher.IsMatch(null); + double result = matcher.IsMatch(null).Score; // Assert Check.That(result).IsEqualTo(0.0d); @@ -79,7 +79,7 @@ public class RegexMatcherTests var matcher = new RegexMatcher(@"\GUIDB", true); // Act - double result = matcher.IsMatch(Guid.NewGuid().ToString("B")); + double result = matcher.IsMatch(Guid.NewGuid().ToString("B")).Score; // Assert result.Should().Be(1.0); @@ -89,10 +89,10 @@ public class RegexMatcherTests public void RegexMatcher_IsMatch_Regex_Guid() { // Assign - var matcher = new RegexMatcher(@"\GUIDB", true, false, false); + var matcher = new RegexMatcher(@"\GUIDB", true, false); // Act - double result = matcher.IsMatch(Guid.NewGuid().ToString("B")); + double result = matcher.IsMatch(Guid.NewGuid().ToString("B")).Score; // Assert result.Should().Be(0); @@ -105,7 +105,7 @@ public class RegexMatcherTests var matcher = new RegexMatcher("H.*o", true); // Act - double result = matcher.IsMatch("hello"); + double result = matcher.IsMatch("hello").Score; // Assert Check.That(result).IsEqualTo(1.0d); @@ -118,7 +118,7 @@ public class RegexMatcherTests var matcher = new RegexMatcher(MatchBehaviour.RejectOnMatch, "h.*o"); // Act - double result = matcher.IsMatch("hello"); + double result = matcher.IsMatch("hello").Score; // Assert Check.That(result).IsEqualTo(0.0); diff --git a/test/WireMock.Net.Tests/Matchers/RequestMatchResultTests.cs b/test/WireMock.Net.Tests/Matchers/RequestMatchResultTests.cs index 8b13d500..42a51c54 100644 --- a/test/WireMock.Net.Tests/Matchers/RequestMatchResultTests.cs +++ b/test/WireMock.Net.Tests/Matchers/RequestMatchResultTests.cs @@ -13,12 +13,12 @@ public class RequestMatchResultTests { // Arrange var result1 = new RequestMatchResult(); - result1.AddScore(typeof(WildcardMatcher), 1); - result1.AddScore(typeof(WildcardMatcher), 0.9); + result1.AddScore(typeof(WildcardMatcher), 1, null); + result1.AddScore(typeof(WildcardMatcher), 0.9, null); var result2 = new RequestMatchResult(); - result2.AddScore(typeof(LinqMatcher), 1); - result2.AddScore(typeof(LinqMatcher), 1); + result2.AddScore(typeof(LinqMatcher), 1, null); + result2.AddScore(typeof(LinqMatcher), 1, null); var results = new[] { result1, result2 }; @@ -34,13 +34,13 @@ public class RequestMatchResultTests { // Arrange var result1 = new RequestMatchResult(); - result1.AddScore(typeof(WildcardMatcher), 1); - result1.AddScore(typeof(WildcardMatcher), 1); + result1.AddScore(typeof(WildcardMatcher), 1, null); + result1.AddScore(typeof(WildcardMatcher), 1, null); var result2 = new RequestMatchResult(); - result2.AddScore(typeof(LinqMatcher), 1); - result2.AddScore(typeof(LinqMatcher), 1); - result2.AddScore(typeof(LinqMatcher), 1); + result2.AddScore(typeof(LinqMatcher), 1, null); + result2.AddScore(typeof(LinqMatcher), 1, null); + result2.AddScore(typeof(LinqMatcher), 1, null); var results = new[] { result1, result2 }; diff --git a/test/WireMock.Net.Tests/Matchers/SimMetricsMatcherTests.cs b/test/WireMock.Net.Tests/Matchers/SimMetricsMatcherTests.cs index 46319a3e..6e0218fb 100644 --- a/test/WireMock.Net.Tests/Matchers/SimMetricsMatcherTests.cs +++ b/test/WireMock.Net.Tests/Matchers/SimMetricsMatcherTests.cs @@ -39,7 +39,7 @@ public class SimMetricsMatcherTests var matcher = new SimMetricsMatcher("The cat walks in the street."); // Act - double result = matcher.IsMatch("The car drives in the street."); + double result = matcher.IsMatch("The car drives in the street.").Score; // Assert Check.That(result).IsStrictlyLessThan(1.0).And.IsStrictlyGreaterThan(0.5); @@ -52,7 +52,7 @@ public class SimMetricsMatcherTests var matcher = new SimMetricsMatcher("The cat walks in the street."); // Act - double result = matcher.IsMatch("Hello"); + double result = matcher.IsMatch("Hello").Score; // Assert Check.That(result).IsStrictlyLessThan(0.1).And.IsStrictlyGreaterThan(0.05); @@ -65,7 +65,7 @@ public class SimMetricsMatcherTests var matcher = new SimMetricsMatcher("test"); // Act - double result = matcher.IsMatch("test"); + double result = matcher.IsMatch("test").Score; // Assert Check.That(result).IsEqualTo(1.0); @@ -78,7 +78,7 @@ public class SimMetricsMatcherTests var matcher = new SimMetricsMatcher(MatchBehaviour.RejectOnMatch, "test"); // Act - double result = matcher.IsMatch("test"); + double result = matcher.IsMatch("test").Score; // Assert Check.That(result).IsEqualTo(0.0); diff --git a/test/WireMock.Net.Tests/Matchers/WildcardMatcherTest.cs b/test/WireMock.Net.Tests/Matchers/WildcardMatcherTest.cs index c3840854..3499a1f0 100644 --- a/test/WireMock.Net.Tests/Matchers/WildcardMatcherTest.cs +++ b/test/WireMock.Net.Tests/Matchers/WildcardMatcherTest.cs @@ -19,11 +19,13 @@ public class WildcardMatcherTest PatternAsFile = "pf" }; - // Act var matcher = new WildcardMatcher(pattern); + // Act + var score = matcher.IsMatch("a").Score; + // Assert - matcher.IsMatch("a").Should().Be(1.0d); + score.Should().Be(1.0d); } [Fact] @@ -39,11 +41,13 @@ public class WildcardMatcherTest Pattern = "b" }; - // Act var matcher = new WildcardMatcher(new [] { pattern1, pattern2 }); + // Act + var score = matcher.IsMatch("a").Score; + // Assert - matcher.IsMatch("a").Should().Be(1.0d); + score.Should().Be(1.0d); } [Fact] @@ -69,7 +73,12 @@ public class WildcardMatcherTest foreach (var test in tests) { var matcher = new WildcardMatcher(test.p); - matcher.IsMatch(test.i).Should().Be(1.0d, $"Pattern '{test.p}' with value '{test.i}' should be 1.0"); + + // Act + var score = matcher.IsMatch(test.i).Score; + + // Assert + score.Should().Be(MatchScores.Perfect, $"Pattern '{test.p}' with value '{test.i}' should be 1.0"); } } @@ -94,7 +103,12 @@ public class WildcardMatcherTest foreach (var test in tests) { var matcher = new WildcardMatcher(test.p); - Check.That(matcher.IsMatch(test.i)).IsEqualTo(0.0); + + // Act + var score = matcher.IsMatch(test.i).Score; + + // Assert + score.Should().Be(MatchScores.Mismatch); } } @@ -105,7 +119,7 @@ public class WildcardMatcherTest var matcher = new WildcardMatcher("x"); // Act - string name = matcher.Name; + var name = matcher.Name; // Assert Check.That(name).Equals("WildcardMatcher"); @@ -131,7 +145,7 @@ public class WildcardMatcherTest var matcher = new WildcardMatcher(MatchBehaviour.RejectOnMatch, "m"); // Act - double result = matcher.IsMatch("m"); + var result = matcher.IsMatch("m").Score; Check.That(result).IsEqualTo(0.0); } diff --git a/test/WireMock.Net.Tests/Matchers/XPathMatcherTests.cs b/test/WireMock.Net.Tests/Matchers/XPathMatcherTests.cs index 19068053..5346f349 100644 --- a/test/WireMock.Net.Tests/Matchers/XPathMatcherTests.cs +++ b/test/WireMock.Net.Tests/Matchers/XPathMatcherTests.cs @@ -43,7 +43,7 @@ public class XPathMatcherTests var matcher = new XPathMatcher("/todo-list[count(todo-item) = 1]"); // Act - double result = matcher.IsMatch(xml); + double result = matcher.IsMatch(xml).Score; // Assert Check.That(result).IsEqualTo(1.0); @@ -57,10 +57,10 @@ public class XPathMatcherTests abc "; - var matcher = new XPathMatcher(MatchBehaviour.RejectOnMatch, false, MatchOperator.Or, "/todo-list[count(todo-item) = 1]"); + var matcher = new XPathMatcher(MatchBehaviour.RejectOnMatch, MatchOperator.Or, "/todo-list[count(todo-item) = 1]"); // Act - double result = matcher.IsMatch(xml); + double result = matcher.IsMatch(xml).Score; // Assert Check.That(result).IsEqualTo(0.0); diff --git a/test/WireMock.Net.Tests/Owin/Mappers/OwinResponseMapperTests.cs b/test/WireMock.Net.Tests/Owin/Mappers/OwinResponseMapperTests.cs index 576f243c..65e4b9a7 100644 --- a/test/WireMock.Net.Tests/Owin/Mappers/OwinResponseMapperTests.cs +++ b/test/WireMock.Net.Tests/Owin/Mappers/OwinResponseMapperTests.cs @@ -1,9 +1,11 @@ +using System; using System.Collections.Generic; using System.IO; using Xunit; using Moq; using System.Threading.Tasks; using System.Threading; +using FluentAssertions; using WireMock.Handlers; using WireMock.Owin.Mappers; using WireMock.ResponseBuilders; @@ -235,6 +237,24 @@ namespace WireMock.Net.Tests.Owin.Mappers #endif } + [Fact] + public void OwinResponseMapper_MapAsync_BodyAsFile_ThrowsException() + { + // Arrange + var responseMessage = new ResponseMessage + { + Headers = new Dictionary>(), + BodyData = new BodyData { DetectedBodyType = BodyType.File, BodyAsFile = string.Empty } + }; + _fileSystemHandlerMock.Setup(f => f.ReadResponseBodyAsFile(It.IsAny())).Throws(); + + // Act + Func action = () => _sut.MapAsync(responseMessage, _responseMock.Object); + + // Assert + action.Should().ThrowAsync(); + } + [Fact] public async Task OwinResponseMapper_MapAsync_WithFault_EMPTY_RESPONSE() { @@ -251,7 +271,7 @@ namespace WireMock.Net.Tests.Owin.Mappers await _sut.MapAsync(responseMessage, _responseMock.Object).ConfigureAwait(false); // Assert - _stream.Verify(s => s.WriteAsync(new byte[0], 0, 0, It.IsAny()), Times.Once); + _stream.Verify(s => s.WriteAsync(EmptyArray.Value, 0, 0, It.IsAny()), Times.Once); } [Theory] diff --git a/test/WireMock.Net.Tests/Owin/MappingMatcherTests.cs b/test/WireMock.Net.Tests/Owin/MappingMatcherTests.cs index b86aced4..49828804 100644 --- a/test/WireMock.Net.Tests/Owin/MappingMatcherTests.cs +++ b/test/WireMock.Net.Tests/Owin/MappingMatcherTests.cs @@ -220,7 +220,7 @@ public class MappingMatcherTests var requestMatchResult = new RequestMatchResult(); foreach (var score in match.scores) { - requestMatchResult.AddScore(typeof(object), score); + requestMatchResult.AddScore(typeof(object), score, null); } mappingMock.SetupGet(m => m.Probability).Returns(match.probability); diff --git a/test/WireMock.Net.Tests/Serialization/CustomPathParamMatcher.cs b/test/WireMock.Net.Tests/Serialization/CustomPathParamMatcher.cs index 34fa6f58..fadb32e6 100644 --- a/test/WireMock.Net.Tests/Serialization/CustomPathParamMatcher.cs +++ b/test/WireMock.Net.Tests/Serialization/CustomPathParamMatcher.cs @@ -15,8 +15,8 @@ namespace WireMock.Net.Tests.Serialization; public class CustomPathParamMatcher : IStringMatcher { public string Name => nameof(CustomPathParamMatcher); + public MatchBehaviour MatchBehaviour { get; } - public bool ThrowException { get; } private readonly string _path; private readonly string[] _pathParts; @@ -30,18 +30,16 @@ public class CustomPathParamMatcher : IStringMatcher MatchBehaviour matchBehaviour, string path, Dictionary pathParams, - bool throwException = false, MatchOperator matchOperator = MatchOperator.Or) { MatchBehaviour = matchBehaviour; - ThrowException = throwException; _path = path; _pathParts = GetPathParts(path); _pathParams = pathParams.ToDictionary(x => x.Key, x => x.Value, StringComparer.OrdinalIgnoreCase); MatchOperator = matchOperator; } - public double IsMatch(string? input) + public MatchResult IsMatch(string? input) { var inputParts = GetPathParts(input); if (inputParts.Length != _pathParts.Length) @@ -79,11 +77,6 @@ public class CustomPathParamMatcher : IStringMatcher } catch { - if (ThrowException) - { - throw; - } - return MatchScores.Mismatch; } diff --git a/test/WireMock.Net.Tests/Serialization/MatcherModelMapperTests.cs b/test/WireMock.Net.Tests/Serialization/MatcherModelMapperTests.cs index a10de874..90ef352c 100644 --- a/test/WireMock.Net.Tests/Serialization/MatcherModelMapperTests.cs +++ b/test/WireMock.Net.Tests/Serialization/MatcherModelMapperTests.cs @@ -43,14 +43,14 @@ public class MatcherModelMapperTests // Assert 1 matcher1.Should().NotBeNull(); - matcher1.IsMatch("x").Should().Be(1.0d); + matcher1.IsMatch("x").Score.Should().Be(1.0d); // Act 2 var matcher2 = (ICSharpCodeMatcher)sut.Map(model)!; // Assert 2 matcher2.Should().NotBeNull(); - matcher2.IsMatch("x").Should().Be(1.0d); + matcher2.IsMatch("x").Score.Should().Be(1.0d); } [Fact] @@ -96,7 +96,6 @@ public class MatcherModelMapperTests // Assert matcher.GetPatterns().Should().ContainSingle("x"); - matcher.ThrowException.Should().BeFalse(); } [Fact] @@ -136,7 +135,6 @@ public class MatcherModelMapperTests matcher.IgnoreCase.Should().BeFalse(); matcher.Value.Should().Be(pattern); matcher.Regex.Should().BeFalse(); - matcher.ThrowException.Should().BeFalse(); } [Fact] @@ -159,43 +157,6 @@ public class MatcherModelMapperTests matcher.IgnoreCase.Should().BeFalse(); matcher.Value.Should().Be(pattern); matcher.Regex.Should().BeTrue(); - matcher.ThrowException.Should().BeFalse(); - } - - [Theory] - [InlineData(nameof(LinqMatcher))] - [InlineData(nameof(ExactMatcher))] - [InlineData(nameof(ExactObjectMatcher))] - [InlineData(nameof(RegexMatcher))] - [InlineData(nameof(JsonMatcher))] - [InlineData(nameof(JsonPartialMatcher))] - [InlineData(nameof(JsonPartialWildcardMatcher))] - [InlineData(nameof(JsonPathMatcher))] - [InlineData(nameof(JmesPathMatcher))] - [InlineData(nameof(XPathMatcher))] - [InlineData(nameof(WildcardMatcher))] - [InlineData(nameof(ContentTypeMatcher))] - [InlineData(nameof(SimMetricsMatcher))] - public void MatcherModelMapper_Map_ThrowExceptionWhenMatcherFails_True(string name) - { - // Assign - var settings = new WireMockServerSettings - { - ThrowExceptionWhenMatcherFails = true - }; - var sut = new MatcherMapper(settings); - var model = new MatcherModel - { - Name = name, - Patterns = new[] { "" } - }; - - // Act - var matcher = sut.Map(model)!; - - // Assert - matcher.Should().NotBeNull(); - matcher.ThrowException.Should().BeTrue(); } [Fact] @@ -249,7 +210,9 @@ public class MatcherModelMapperTests // Assert Check.That(matcher.GetPatterns()).ContainsExactly("x", "y"); - Check.That(matcher.IsMatch("X")).IsEqualTo(expected); + + var result = matcher.IsMatch("X"); + result.Score.Should().Be(expected); } [Theory] @@ -272,7 +235,9 @@ public class MatcherModelMapperTests // Assert Check.That(matcher.GetPatterns()).ContainsExactly("x", "y"); - Check.That(matcher.IsMatch("X")).IsEqualTo(expected); + + var result = matcher.IsMatch("X"); + result.Score.Should().Be(expected); } [Fact] @@ -306,7 +271,9 @@ public class MatcherModelMapperTests // Assert matcher.GetPatterns().Should().HaveCount(1).And.Contain(new AnyOf(stringPattern)); - matcher.IsMatch("c").Should().Be(1.0d); + + var result = matcher.IsMatch("c"); + result.Score.Should().Be(MatchScores.Perfect); } [Fact] @@ -395,8 +362,7 @@ public class MatcherModelMapperTests return new CustomPathParamMatcher( matcherModel.RejectOnMatch == true ? MatchBehaviour.RejectOnMatch : MatchBehaviour.AcceptOnMatch, matcherParams.Path, - matcherParams.PathParams, - settings.ThrowExceptionWhenMatcherFails == true + matcherParams.PathParams ); }; var sut = new MatcherMapper(settings); diff --git a/test/WireMock.Net.Tests/WireMockAdminApiTests.IWireMockAdminApi_GetMappingsCode.verified.txt b/test/WireMock.Net.Tests/WireMockAdminApiTests.IWireMockAdminApi_GetMappingsCode.verified.txt index 4ba964e0..2b7410d8 100644 --- a/test/WireMock.Net.Tests/WireMockAdminApiTests.IWireMockAdminApi_GetMappingsCode.verified.txt +++ b/test/WireMock.Net.Tests/WireMockAdminApiTests.IWireMockAdminApi_GetMappingsCode.verified.txt @@ -77,7 +77,6 @@ server .WithBody(new JsonPartialMatcher( value: "{ a = 1, b = 2 }", ignoreCase: false, - throwException: false, regex: false )) ) diff --git a/test/WireMock.Net.Tests/WireMockServerTests.cs b/test/WireMock.Net.Tests/WireMockServerTests.cs index 751c0c7b..1cd2e989 100644 --- a/test/WireMock.Net.Tests/WireMockServerTests.cs +++ b/test/WireMock.Net.Tests/WireMockServerTests.cs @@ -138,25 +138,25 @@ public partial class WireMockServerTests #if NETCOREAPP3_1 || NET5_0 || NET6_0 || NET7_0 [Fact] -public async Task WireMockServer_WithCorsPolicyOptions_Should_Work_Correct() -{ - // Arrange - var settings = new WireMockServerSettings + public async Task WireMockServer_WithCorsPolicyOptions_Should_Work_Correct() { - CorsPolicyOptions = CorsPolicyOptions.AllowAll - }; - var server = WireMockServer.Start(settings); + // Arrange + var settings = new WireMockServerSettings + { + CorsPolicyOptions = CorsPolicyOptions.AllowAll + }; + var server = WireMockServer.Start(settings); - server.Given(Request.Create().WithPath("/*")).RespondWith(Response.Create().WithBody("x")); + server.Given(Request.Create().WithPath("/*")).RespondWith(Response.Create().WithBody("x")); - // Act - var response = await new HttpClient().GetStringAsync("http://localhost:" + server.Ports[0] + "/foo").ConfigureAwait(false); + // Act + var response = await new HttpClient().GetStringAsync("http://localhost:" + server.Ports[0] + "/foo").ConfigureAwait(false); - // Asser. - response.Should().Be("x"); + // Asser. + response.Should().Be("x"); - server.Stop(); -} + server.Stop(); + } #endif [Fact] @@ -277,34 +277,34 @@ public async Task WireMockServer_WithCorsPolicyOptions_Should_Work_Correct() } #if !NET452 && !NET461 -[Theory] -[InlineData("TRACE")] -[InlineData("GET")] -public async Task WireMockServer_Should_exclude_body_for_methods_where_body_is_definitely_disallowed(string method) -{ - // Assign - string content = "hello"; - var server = WireMockServer.Start(); + [Theory] + [InlineData("TRACE")] + [InlineData("GET")] + public async Task WireMockServer_Should_exclude_body_for_methods_where_body_is_definitely_disallowed(string method) + { + // Assign + string content = "hello"; + var server = WireMockServer.Start(); - server - .Given(Request.Create().WithBody((byte[] bodyBytes) => bodyBytes != null)) - .AtPriority(0) - .RespondWith(Response.Create().WithStatusCode(400)); - server - .Given(Request.Create()) - .AtPriority(1) - .RespondWith(Response.Create().WithStatusCode(200)); + server + .Given(Request.Create().WithBody((byte[] bodyBytes) => bodyBytes != null)) + .AtPriority(0) + .RespondWith(Response.Create().WithStatusCode(400)); + server + .Given(Request.Create()) + .AtPriority(1) + .RespondWith(Response.Create().WithStatusCode(200)); - // Act - var request = new HttpRequestMessage(new HttpMethod(method), "http://localhost:" + server.Ports[0] + "/"); - request.Content = new StringContent(content); - var response = await new HttpClient().SendAsync(request).ConfigureAwait(false); + // Act + var request = new HttpRequestMessage(new HttpMethod(method), "http://localhost:" + server.Ports[0] + "/"); + request.Content = new StringContent(content); + var response = await new HttpClient().SendAsync(request).ConfigureAwait(false); - // Assert - Check.That(response.StatusCode).Equals(HttpStatusCode.OK); + // Assert + Check.That(response.StatusCode).Equals(HttpStatusCode.OK); - server.Stop(); -} + server.Stop(); + } #endif [Theory] @@ -462,11 +462,10 @@ public async Task WireMockServer_Should_exclude_body_for_methods_where_body_is_d settings.CustomMatcherMappings = new Dictionary>(); settings.CustomMatcherMappings[nameof(CustomPathParamMatcher)] = matcherModel => { - var matcherParams = JsonConvert.DeserializeObject((string)matcherModel.Pattern); + var matcherParams = JsonConvert.DeserializeObject((string)matcherModel.Pattern!)!; return new CustomPathParamMatcher( matcherModel.RejectOnMatch == true ? MatchBehaviour.RejectOnMatch : MatchBehaviour.AcceptOnMatch, - matcherParams.Path, matcherParams.PathParams, - settings.ThrowExceptionWhenMatcherFails == true + matcherParams.Path, matcherParams.PathParams ); }; @@ -510,11 +509,10 @@ public async Task WireMockServer_Should_exclude_body_for_methods_where_body_is_d settings.CustomMatcherMappings = new Dictionary>(); settings.CustomMatcherMappings[nameof(CustomPathParamMatcher)] = matcherModel => { - var matcherParams = JsonConvert.DeserializeObject((string)matcherModel.Pattern); + var matcherParams = JsonConvert.DeserializeObject((string)matcherModel.Pattern!)!; return new CustomPathParamMatcher( matcherModel.RejectOnMatch == true ? MatchBehaviour.RejectOnMatch : MatchBehaviour.AcceptOnMatch, - matcherParams.Path, matcherParams.PathParams, - settings.ThrowExceptionWhenMatcherFails == true + matcherParams.Path, matcherParams.PathParams ); };