diff --git a/src/WireMock.Net/Admin/Mappings/MatcherModel.cs b/src/WireMock.Net/Admin/Mappings/MatcherModel.cs index cb71a454..54266b80 100644 --- a/src/WireMock.Net/Admin/Mappings/MatcherModel.cs +++ b/src/WireMock.Net/Admin/Mappings/MatcherModel.cs @@ -8,33 +8,21 @@ /// /// Gets or sets the name. /// - /// - /// The name. - /// public string Name { get; set; } /// /// Gets or sets the pattern. /// - /// - /// The pattern. - /// public string Pattern { get; set; } /// /// Gets or sets the patterns. /// - /// - /// The patterns. - /// public string[] Patterns { get; set; } /// /// Gets or sets the ignore case. /// - /// - /// The ignore case. - /// public bool? IgnoreCase { get; set; } } } diff --git a/src/WireMock.Net/Matchers/ExactMatcher.cs b/src/WireMock.Net/Matchers/ExactMatcher.cs index 5923140e..002a0cc2 100644 --- a/src/WireMock.Net/Matchers/ExactMatcher.cs +++ b/src/WireMock.Net/Matchers/ExactMatcher.cs @@ -18,7 +18,7 @@ namespace WireMock.Matchers /// The values. public ExactMatcher([NotNull] params string[] values) { - Check.NotNull(values, nameof(values)); + Check.HasNoNulls(values, nameof(values)); _values = values; } diff --git a/src/WireMock.Net/Matchers/Request/RequestMessageCompositeMatcher.cs b/src/WireMock.Net/Matchers/Request/RequestMessageCompositeMatcher.cs index 4139f980..50e681e4 100644 --- a/src/WireMock.Net/Matchers/Request/RequestMessageCompositeMatcher.cs +++ b/src/WireMock.Net/Matchers/Request/RequestMessageCompositeMatcher.cs @@ -33,14 +33,7 @@ namespace WireMock.Matchers.Request RequestMatchers = requestMatchers; } - /// - /// Determines whether the specified RequestMessage is match. - /// - /// The RequestMessage. - /// The RequestMatchResult. - /// - /// A value between 0.0 - 1.0 of the similarity. - /// + /// public double GetMatchingScore(RequestMessage requestMessage, RequestMatchResult requestMatchResult) { if (!RequestMatchers.Any()) diff --git a/src/WireMock.Net/Matchers/Request/RequestMessageCookieMatcher.cs b/src/WireMock.Net/Matchers/Request/RequestMessageCookieMatcher.cs index f2b0b2e9..795bd243 100644 --- a/src/WireMock.Net/Matchers/Request/RequestMessageCookieMatcher.cs +++ b/src/WireMock.Net/Matchers/Request/RequestMessageCookieMatcher.cs @@ -66,14 +66,7 @@ namespace WireMock.Matchers.Request Funcs = funcs; } - /// - /// Determines whether the specified RequestMessage is match. - /// - /// The RequestMessage. - /// The RequestMatchResult. - /// - /// A value between 0.0 - 1.0 of the similarity. - /// + /// public double GetMatchingScore(RequestMessage requestMessage, RequestMatchResult requestMatchResult) { double score = IsMatch(requestMessage); diff --git a/src/WireMock.Net/ResponseBuilders/BodyDestinationFormat.cs b/src/WireMock.Net/ResponseBuilders/BodyDestinationFormat.cs index 8718a520..01f0061f 100644 --- a/src/WireMock.Net/ResponseBuilders/BodyDestinationFormat.cs +++ b/src/WireMock.Net/ResponseBuilders/BodyDestinationFormat.cs @@ -19,5 +19,10 @@ /// Convert to bytes /// public const string Bytes = "Bytes"; + + /// + /// Convert to Json object + /// + public const string Json = "Json"; } } \ No newline at end of file diff --git a/src/WireMock.Net/ResponseBuilders/Response.cs b/src/WireMock.Net/ResponseBuilders/Response.cs index 292e0b0d..dde017ea 100644 --- a/src/WireMock.Net/ResponseBuilders/Response.cs +++ b/src/WireMock.Net/ResponseBuilders/Response.cs @@ -1,366 +1,373 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Net; -using System.Net.Http; -using System.Text; -using System.Threading.Tasks; -using JetBrains.Annotations; -using WireMock.Http; -using WireMock.Settings; -using WireMock.Transformers; -using WireMock.Util; -using WireMock.Validation; - -namespace WireMock.ResponseBuilders -{ - /// - /// The Response. - /// - public class Response : IResponseBuilder - { - private HttpClient _httpClientForProxy; - - /// - /// The delay - /// - public TimeSpan? Delay { get; private set; } - - /// - /// Gets a value indicating whether [use transformer]. - /// - /// - /// true if [use transformer]; otherwise, false. - /// - public bool UseTransformer { get; private set; } - - /// - /// The Proxy URL to use. - /// - public string ProxyUrl { get; private set; } - - /// - /// The client X509Certificate2 Thumbprint or SubjectName to use. - /// - public string ClientX509Certificate2ThumbprintOrSubjectName { get; private set; } - - /// - /// Gets the response message. - /// - public ResponseMessage ResponseMessage { get; } - - /// - /// A delegate to execute to generate the response - /// - public Func Callback { get; private set; } - - /// - /// Creates this instance. - /// - /// ResponseMessage - /// A . - [PublicAPI] - public static IResponseBuilder Create([CanBeNull] ResponseMessage responseMessage = null) - { - var message = responseMessage ?? new ResponseMessage { StatusCode = (int)HttpStatusCode.OK }; - return new Response(message); - } - - /// - /// Creates this instance. - /// - /// A . - [PublicAPI] - public static IResponseBuilder Create([NotNull] Func func) - { - Check.NotNull(func, nameof(func)); - - return new Response(func()); - } - - /// - /// Initializes a new instance of the class. - /// - /// - /// The response. - /// - private Response(ResponseMessage responseMessage) - { - ResponseMessage = responseMessage; - } - - /// - /// The with status code. - /// - /// The code. - /// A .\ - [PublicAPI] - public IResponseBuilder WithStatusCode(int code) - { - ResponseMessage.StatusCode = code; - return this; - } - - /// - /// The with status code. - /// - /// The code. - /// A . - [PublicAPI] - public IResponseBuilder WithStatusCode(HttpStatusCode code) - { - return WithStatusCode((int)code); - } - - /// - /// The with Success status code (200). - /// - /// A . - [PublicAPI] - public IResponseBuilder WithSuccess() - { - return WithStatusCode((int)HttpStatusCode.OK); - } - - /// - /// The with NotFound status code (404). - /// - /// The . - [PublicAPI] - public IResponseBuilder WithNotFound() - { - return WithStatusCode((int)HttpStatusCode.NotFound); - } - - /// - public IResponseBuilder WithHeader(string name, params string[] values) - { - Check.NotNull(name, nameof(name)); - - ResponseMessage.AddHeader(name, values); - return this; - } - - /// - public IResponseBuilder WithHeaders(IDictionary headers) - { - Check.NotNull(headers, nameof(headers)); - - ResponseMessage.Headers = headers.ToDictionary(header => header.Key, header => new WireMockList(header.Value)); - return this; - } - - /// - public IResponseBuilder WithHeaders(IDictionary headers) - { - Check.NotNull(headers, nameof(headers)); - - ResponseMessage.Headers = headers.ToDictionary(header => header.Key, header => new WireMockList(header.Value)); - return this; - } - - /// - public IResponseBuilder WithHeaders(IDictionary> headers) - { - ResponseMessage.Headers = headers; - return this; - } - +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net; +using System.Net.Http; +using System.Text; +using System.Threading.Tasks; +using JetBrains.Annotations; +using Newtonsoft.Json; +using WireMock.Http; +using WireMock.Settings; +using WireMock.Transformers; +using WireMock.Util; +using WireMock.Validation; + +namespace WireMock.ResponseBuilders +{ + /// + /// The Response. + /// + public class Response : IResponseBuilder + { + private HttpClient _httpClientForProxy; + + /// + /// The delay + /// + public TimeSpan? Delay { get; private set; } + + /// + /// Gets a value indicating whether [use transformer]. + /// + /// + /// true if [use transformer]; otherwise, false. + /// + public bool UseTransformer { get; private set; } + + /// + /// The Proxy URL to use. + /// + public string ProxyUrl { get; private set; } + + /// + /// The client X509Certificate2 Thumbprint or SubjectName to use. + /// + public string ClientX509Certificate2ThumbprintOrSubjectName { get; private set; } + + /// + /// Gets the response message. + /// + public ResponseMessage ResponseMessage { get; } + + /// + /// A delegate to execute to generate the response + /// + public Func Callback { get; private set; } + + /// + /// Creates this instance. + /// + /// ResponseMessage + /// A . + [PublicAPI] + public static IResponseBuilder Create([CanBeNull] ResponseMessage responseMessage = null) + { + var message = responseMessage ?? new ResponseMessage { StatusCode = (int)HttpStatusCode.OK }; + return new Response(message); + } + + /// + /// Creates this instance. + /// + /// A . + [PublicAPI] + public static IResponseBuilder Create([NotNull] Func func) + { + Check.NotNull(func, nameof(func)); + + return new Response(func()); + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// The response. + /// + private Response(ResponseMessage responseMessage) + { + ResponseMessage = responseMessage; + } + + /// + /// The with status code. + /// + /// The code. + /// A .\ + [PublicAPI] + public IResponseBuilder WithStatusCode(int code) + { + ResponseMessage.StatusCode = code; + return this; + } + + /// + /// The with status code. + /// + /// The code. + /// A . + [PublicAPI] + public IResponseBuilder WithStatusCode(HttpStatusCode code) + { + return WithStatusCode((int)code); + } + + /// + /// The with Success status code (200). + /// + /// A . + [PublicAPI] + public IResponseBuilder WithSuccess() + { + return WithStatusCode((int)HttpStatusCode.OK); + } + + /// + /// The with NotFound status code (404). + /// + /// The . + [PublicAPI] + public IResponseBuilder WithNotFound() + { + return WithStatusCode((int)HttpStatusCode.NotFound); + } + + /// + public IResponseBuilder WithHeader(string name, params string[] values) + { + Check.NotNull(name, nameof(name)); + + ResponseMessage.AddHeader(name, values); + return this; + } + + /// + public IResponseBuilder WithHeaders(IDictionary headers) + { + Check.NotNull(headers, nameof(headers)); + + ResponseMessage.Headers = headers.ToDictionary(header => header.Key, header => new WireMockList(header.Value)); + return this; + } + + /// + public IResponseBuilder WithHeaders(IDictionary headers) + { + Check.NotNull(headers, nameof(headers)); + + ResponseMessage.Headers = headers.ToDictionary(header => header.Key, header => new WireMockList(header.Value)); + return this; + } + + /// + public IResponseBuilder WithHeaders(IDictionary> headers) + { + ResponseMessage.Headers = headers; + return this; + } + /// - public IResponseBuilder WithBody(Func bodyFactory, string destination = BodyDestinationFormat.SameAsSource, - Encoding encoding = null) - { - return WithCallback(req => new ResponseMessage {Body = bodyFactory(req)}); - } - - /// - public IResponseBuilder WithBody(byte[] body, string destination, Encoding encoding = null) - { - Check.NotNull(body, nameof(body)); - - ResponseMessage.BodyDestination = destination; - - switch (destination) - { - case BodyDestinationFormat.String: - var enc = encoding ?? Encoding.UTF8; - ResponseMessage.BodyAsBytes = null; - ResponseMessage.Body = enc.GetString(body); - ResponseMessage.BodyEncoding = enc; - break; - - default: - ResponseMessage.BodyAsBytes = body; - ResponseMessage.BodyEncoding = null; - break; - } - - return this; - } - - /// - public IResponseBuilder WithBodyFromFile(string filename, bool cache = true) - { - Check.NotNull(filename, nameof(filename)); - - ResponseMessage.BodyEncoding = null; - ResponseMessage.BodyAsFileIsCached = cache; - - if (cache) - { - ResponseMessage.Body = null; - ResponseMessage.BodyAsBytes = File.ReadAllBytes(filename); - ResponseMessage.BodyAsFile = null; - } - else - { - ResponseMessage.Body = null; - ResponseMessage.BodyAsBytes = null; - ResponseMessage.BodyAsFile = filename; - } - - return this; - } - - /// - public IResponseBuilder WithBody(string body, string destination = BodyDestinationFormat.SameAsSource, Encoding encoding = null) - { - Check.NotNull(body, nameof(body)); - - encoding = encoding ?? Encoding.UTF8; - - ResponseMessage.BodyDestination = destination; - - switch (destination) - { - case BodyDestinationFormat.Bytes: - ResponseMessage.Body = null; - ResponseMessage.BodyAsBytes = encoding.GetBytes(body); - ResponseMessage.BodyEncoding = encoding; - break; - - default: - ResponseMessage.Body = body; - ResponseMessage.BodyAsBytes = null; - ResponseMessage.BodyEncoding = encoding; - break; - } - - return this; - } - - /// - public IResponseBuilder WithBodyAsJson(object body, Encoding encoding = null) - { - Check.NotNull(body, nameof(body)); - - ResponseMessage.BodyDestination = null; - ResponseMessage.BodyAsJson = body; - ResponseMessage.BodyEncoding = encoding; - - return this; - } - - /// - public IResponseBuilder WithBodyFromBase64(string bodyAsbase64, Encoding encoding = null) - { - Check.NotNull(bodyAsbase64, nameof(bodyAsbase64)); - - encoding = encoding ?? Encoding.UTF8; - - ResponseMessage.BodyDestination = null; - ResponseMessage.Body = encoding.GetString(Convert.FromBase64String(bodyAsbase64)); - ResponseMessage.BodyEncoding = encoding; - - return this; - } - - /// - public IResponseBuilder WithTransformer() - { - UseTransformer = true; - return this; - } - - /// - public IResponseBuilder WithDelay(TimeSpan delay) - { - Check.Condition(delay, d => d > TimeSpan.Zero, nameof(delay)); - - Delay = delay; - return this; - } - - /// - public IResponseBuilder WithDelay(int milliseconds) - { - return WithDelay(TimeSpan.FromMilliseconds(milliseconds)); - } - - /// - public IResponseBuilder WithProxy(string proxyUrl, string clientX509Certificate2ThumbprintOrSubjectName = null) - { - Check.NotNullOrEmpty(proxyUrl, nameof(proxyUrl)); - - ProxyUrl = proxyUrl; - ClientX509Certificate2ThumbprintOrSubjectName = clientX509Certificate2ThumbprintOrSubjectName; - _httpClientForProxy = HttpClientHelper.CreateHttpClient(clientX509Certificate2ThumbprintOrSubjectName); - return this; - } - - /// - public IResponseBuilder WithProxy(IProxyAndRecordSettings settings) - { - Check.NotNull(settings, nameof(settings)); - - return WithProxy(settings.Url, settings.ClientX509Certificate2ThumbprintOrSubjectName); - } - - /// - public IResponseBuilder WithCallback(Func callbackHandler) - { - Check.NotNull(callbackHandler, nameof(callbackHandler)); - - Callback = callbackHandler; - - return this; - } - - /// - /// The provide response. - /// - /// The request. - /// The . - public async Task ProvideResponseAsync(RequestMessage requestMessage) - { - Check.NotNull(requestMessage, nameof(requestMessage)); - - if (Delay != null) - { - await Task.Delay(Delay.Value); - } - - if (ProxyUrl != null && _httpClientForProxy != null) - { - var requestUri = new Uri(requestMessage.Url); - var proxyUri = new Uri(ProxyUrl); - var proxyUriWithRequestPathAndQuery = new Uri(proxyUri, requestUri.PathAndQuery); - - return await HttpClientHelper.SendAsync(_httpClientForProxy, requestMessage, proxyUriWithRequestPathAndQuery.AbsoluteUri); - } - - if (UseTransformer) - { - return ResponseMessageTransformer.Transform(requestMessage, ResponseMessage); - } - - if (Callback != null) - { - return Callback(requestMessage); - } - - return ResponseMessage; - } - } + public IResponseBuilder WithBody(Func bodyFactory, string destination = BodyDestinationFormat.SameAsSource, Encoding encoding = null) + { + return WithCallback(req => new ResponseMessage { Body = bodyFactory(req) }); + } + + /// + public IResponseBuilder WithBody(byte[] body, string destination, Encoding encoding = null) + { + Check.NotNull(body, nameof(body)); + + ResponseMessage.BodyDestination = destination; + + switch (destination) + { + case BodyDestinationFormat.String: + var enc = encoding ?? Encoding.UTF8; + ResponseMessage.BodyAsBytes = null; + ResponseMessage.Body = enc.GetString(body); + ResponseMessage.BodyEncoding = enc; + break; + + default: + ResponseMessage.BodyAsBytes = body; + ResponseMessage.BodyEncoding = null; + break; + } + + return this; + } + + /// + public IResponseBuilder WithBodyFromFile(string filename, bool cache = true) + { + Check.NotNull(filename, nameof(filename)); + + ResponseMessage.BodyEncoding = null; + ResponseMessage.BodyAsFileIsCached = cache; + + if (cache) + { + ResponseMessage.Body = null; + ResponseMessage.BodyAsBytes = File.ReadAllBytes(filename); + ResponseMessage.BodyAsFile = null; + } + else + { + ResponseMessage.Body = null; + ResponseMessage.BodyAsBytes = null; + ResponseMessage.BodyAsFile = filename; + } + + return this; + } + + /// + public IResponseBuilder WithBody(string body, string destination = BodyDestinationFormat.SameAsSource, Encoding encoding = null) + { + Check.NotNull(body, nameof(body)); + + encoding = encoding ?? Encoding.UTF8; + + ResponseMessage.BodyDestination = destination; + ResponseMessage.BodyEncoding = encoding; + + switch (destination) + { + case BodyDestinationFormat.Bytes: + ResponseMessage.Body = null; + ResponseMessage.BodyAsJson = null; + ResponseMessage.BodyAsBytes = encoding.GetBytes(body); + break; + + case BodyDestinationFormat.Json: + ResponseMessage.Body = null; + ResponseMessage.BodyAsJson = JsonConvert.DeserializeObject(body); + ResponseMessage.BodyAsBytes = null; + break; + + default: + ResponseMessage.Body = body; + ResponseMessage.BodyAsJson = null; + ResponseMessage.BodyAsBytes = null; + break; + } + + return this; + } + + /// + public IResponseBuilder WithBodyAsJson(object body, Encoding encoding = null) + { + Check.NotNull(body, nameof(body)); + + ResponseMessage.BodyDestination = null; + ResponseMessage.BodyAsJson = body; + ResponseMessage.BodyEncoding = encoding; + + return this; + } + + /// + public IResponseBuilder WithBodyFromBase64(string bodyAsbase64, Encoding encoding = null) + { + Check.NotNull(bodyAsbase64, nameof(bodyAsbase64)); + + encoding = encoding ?? Encoding.UTF8; + + ResponseMessage.BodyDestination = null; + ResponseMessage.Body = encoding.GetString(Convert.FromBase64String(bodyAsbase64)); + ResponseMessage.BodyEncoding = encoding; + + return this; + } + + /// + public IResponseBuilder WithTransformer() + { + UseTransformer = true; + return this; + } + + /// + public IResponseBuilder WithDelay(TimeSpan delay) + { + Check.Condition(delay, d => d > TimeSpan.Zero, nameof(delay)); + + Delay = delay; + return this; + } + + /// + public IResponseBuilder WithDelay(int milliseconds) + { + return WithDelay(TimeSpan.FromMilliseconds(milliseconds)); + } + + /// + public IResponseBuilder WithProxy(string proxyUrl, string clientX509Certificate2ThumbprintOrSubjectName = null) + { + Check.NotNullOrEmpty(proxyUrl, nameof(proxyUrl)); + + ProxyUrl = proxyUrl; + ClientX509Certificate2ThumbprintOrSubjectName = clientX509Certificate2ThumbprintOrSubjectName; + _httpClientForProxy = HttpClientHelper.CreateHttpClient(clientX509Certificate2ThumbprintOrSubjectName); + return this; + } + + /// + public IResponseBuilder WithProxy(IProxyAndRecordSettings settings) + { + Check.NotNull(settings, nameof(settings)); + + return WithProxy(settings.Url, settings.ClientX509Certificate2ThumbprintOrSubjectName); + } + + /// + public IResponseBuilder WithCallback(Func callbackHandler) + { + Check.NotNull(callbackHandler, nameof(callbackHandler)); + + Callback = callbackHandler; + + return this; + } + + /// + /// The provide response. + /// + /// The request. + /// The . + public async Task ProvideResponseAsync(RequestMessage requestMessage) + { + Check.NotNull(requestMessage, nameof(requestMessage)); + + if (Delay != null) + { + await Task.Delay(Delay.Value); + } + + if (ProxyUrl != null && _httpClientForProxy != null) + { + var requestUri = new Uri(requestMessage.Url); + var proxyUri = new Uri(ProxyUrl); + var proxyUriWithRequestPathAndQuery = new Uri(proxyUri, requestUri.PathAndQuery); + + return await HttpClientHelper.SendAsync(_httpClientForProxy, requestMessage, proxyUriWithRequestPathAndQuery.AbsoluteUri); + } + + if (UseTransformer) + { + return ResponseMessageTransformer.Transform(requestMessage, ResponseMessage); + } + + if (Callback != null) + { + return Callback(requestMessage); + } + + return ResponseMessage; + } + } } \ No newline at end of file diff --git a/src/WireMock.Net/Serialization/MappingConverter.cs b/src/WireMock.Net/Serialization/MappingConverter.cs index 3c4b0a83..deb23349 100644 --- a/src/WireMock.Net/Serialization/MappingConverter.cs +++ b/src/WireMock.Net/Serialization/MappingConverter.cs @@ -2,9 +2,7 @@ using System.Collections.Generic; using System.Linq; using JetBrains.Annotations; -using SimMetrics.Net; using WireMock.Admin.Mappings; -using WireMock.Matchers; using WireMock.Matchers.Request; using WireMock.RequestBuilders; using WireMock.ResponseBuilders; @@ -40,19 +38,19 @@ namespace WireMock.Serialization { ClientIP = clientIPMatchers != null && clientIPMatchers.Any() ? new ClientIPModel { - Matchers = Map(clientIPMatchers.Where(m => m.Matchers != null).SelectMany(m => m.Matchers)), + Matchers = MatcherMapper.Map(clientIPMatchers.Where(m => m.Matchers != null).SelectMany(m => m.Matchers)), Funcs = Map(clientIPMatchers.Where(m => m.Funcs != null).SelectMany(m => m.Funcs)) } : null, Path = pathMatchers != null && pathMatchers.Any() ? new PathModel { - Matchers = Map(pathMatchers.Where(m => m.Matchers != null).SelectMany(m => m.Matchers)), + Matchers = MatcherMapper.Map(pathMatchers.Where(m => m.Matchers != null).SelectMany(m => m.Matchers)), Funcs = Map(pathMatchers.Where(m => m.Funcs != null).SelectMany(m => m.Funcs)) } : null, Url = urlMatchers != null && urlMatchers.Any() ? new UrlModel { - Matchers = Map(urlMatchers.Where(m => m.Matchers != null).SelectMany(m => m.Matchers)), + Matchers = MatcherMapper.Map(urlMatchers.Where(m => m.Matchers != null).SelectMany(m => m.Matchers)), Funcs = Map(urlMatchers.Where(m => m.Funcs != null).SelectMany(m => m.Funcs)) } : null, @@ -61,14 +59,14 @@ namespace WireMock.Serialization Headers = headerMatchers != null && headerMatchers.Any() ? headerMatchers.Select(hm => new HeaderModel { Name = hm.Name, - Matchers = Map(hm.Matchers), + Matchers = MatcherMapper.Map(hm.Matchers), Funcs = Map(hm.Funcs) }).ToList() : null, Cookies = cookieMatchers != null && cookieMatchers.Any() ? cookieMatchers.Select(cm => new CookieModel { Name = cm.Name, - Matchers = Map(cm.Matchers), + Matchers = MatcherMapper.Map(cm.Matchers), Funcs = Map(cm.Funcs) }).ToList() : null, @@ -81,7 +79,7 @@ namespace WireMock.Serialization Body = methodMatcher?.Methods != null && methodMatcher.Methods.Any(m => m == "get") ? null : new BodyModel { - Matcher = bodyMatcher != null ? Map(bodyMatcher.Matcher) : null, + Matcher = bodyMatcher != null ? MatcherMapper.Map(bodyMatcher.Matcher) : null, Func = bodyMatcher != null ? Map(bodyMatcher.Func) : null, DataFunc = bodyMatcher != null ? Map(bodyMatcher.DataFunc) : null } @@ -149,87 +147,16 @@ namespace WireMock.Serialization return newDictionary; } - private static MatcherModel[] Map([CanBeNull] IEnumerable matchers) - { - if (matchers == null || !matchers.Any()) - { - return null; - } - - return matchers.Select(Map).Where(x => x != null).ToArray(); - } - - private static MatcherModel Map([CanBeNull] IMatcher matcher) - { - if (matcher == null) - { - return null; - } - - IStringMatcher stringMatcher = matcher as IStringMatcher; - string[] patterns = stringMatcher != null ? stringMatcher.GetPatterns() : new string[0]; - - return new MatcherModel - { - Name = matcher.GetName(), - Pattern = patterns.Length == 1 ? patterns.First() : null, - Patterns = patterns.Length > 1 ? patterns : null - }; - } + private static string[] Map([CanBeNull] IEnumerable> funcs) { - if (funcs == null || !funcs.Any()) - return null; - - return funcs.Select(Map).Where(x => x != null).ToArray(); + return funcs?.Select(Map).Where(x => x != null).ToArray(); } private static string Map([CanBeNull] Func func) { return func?.ToString(); } - - public static IMatcher Map([CanBeNull] MatcherModel matcher) - { - if (matcher == null) - { - return null; - } - - var parts = matcher.Name.Split('.'); - string matcherName = parts[0]; - string matcherType = parts.Length > 1 ? parts[1] : null; - - string[] patterns = matcher.Patterns ?? new[] { matcher.Pattern }; - - switch (matcherName) - { - case "ExactMatcher": - return new ExactMatcher(patterns); - - case "RegexMatcher": - return new RegexMatcher(patterns); - - case "JsonPathMatcher": - return new JsonPathMatcher(patterns); - - case "XPathMatcher": - return new XPathMatcher(matcher.Pattern); - - case "WildcardMatcher": - return new WildcardMatcher(patterns, matcher.IgnoreCase == true); - - case "SimMetricsMatcher": - SimMetricType type = SimMetricType.Levenstein; - if (!string.IsNullOrEmpty(matcherType) && !Enum.TryParse(matcherType, out type)) - throw new NotSupportedException($"Matcher '{matcherName}' with Type '{matcherType}' is not supported."); - - return new SimMetricsMatcher(matcher.Pattern, type); - - default: - throw new NotSupportedException($"Matcher '{matcherName}' is not supported."); - } - } } } \ No newline at end of file diff --git a/src/WireMock.Net/Serialization/MatcherMapper.cs b/src/WireMock.Net/Serialization/MatcherMapper.cs new file mode 100644 index 00000000..40785582 --- /dev/null +++ b/src/WireMock.Net/Serialization/MatcherMapper.cs @@ -0,0 +1,34 @@ +using System.Collections.Generic; +using System.Linq; +using JetBrains.Annotations; +using WireMock.Admin.Mappings; +using WireMock.Matchers; + +namespace WireMock.Serialization +{ + internal static class MatcherMapper + { + public static MatcherModel[] Map([CanBeNull] IEnumerable matchers) + { + return matchers?.Select(Map).Where(x => x != null).ToArray(); + } + + public static MatcherModel Map([CanBeNull] IMatcher matcher) + { + if (matcher == null) + { + return null; + } + + IStringMatcher stringMatcher = matcher as IStringMatcher; + string[] patterns = stringMatcher != null ? stringMatcher.GetPatterns() : new string[0]; + + return new MatcherModel + { + Name = matcher.GetName(), + Pattern = patterns.Length == 1 ? patterns.First() : null, + Patterns = patterns.Length > 1 ? patterns : null + }; + } + } +} diff --git a/src/WireMock.Net/Serialization/MatcherModelMapper.cs b/src/WireMock.Net/Serialization/MatcherModelMapper.cs new file mode 100644 index 00000000..78c1e630 --- /dev/null +++ b/src/WireMock.Net/Serialization/MatcherModelMapper.cs @@ -0,0 +1,55 @@ +using System; +using JetBrains.Annotations; +using SimMetrics.Net; +using WireMock.Admin.Mappings; +using WireMock.Matchers; + +namespace WireMock.Serialization +{ + internal static class MatcherModelMapper + { + public static IMatcher Map([CanBeNull] MatcherModel matcher) + { + if (matcher == null) + { + return null; + } + + string[] parts = matcher.Name.Split('.'); + string matcherName = parts[0]; + string matcherType = parts.Length > 1 ? parts[1] : null; + + string[] patterns = matcher.Patterns ?? new[] { matcher.Pattern }; + + switch (matcherName) + { + case "ExactMatcher": + return new ExactMatcher(patterns); + + case "RegexMatcher": + return new RegexMatcher(patterns, matcher.IgnoreCase == true); + + case "JsonPathMatcher": + return new JsonPathMatcher(patterns); + + case "XPathMatcher": + return new XPathMatcher(matcher.Pattern); + + case "WildcardMatcher": + return new WildcardMatcher(patterns, matcher.IgnoreCase == true); + + case "SimMetricsMatcher": + SimMetricType type = SimMetricType.Levenstein; + if (!string.IsNullOrEmpty(matcherType) && !Enum.TryParse(matcherType, out type)) + { + throw new NotSupportedException($"Matcher '{matcherName}' with Type '{matcherType}' is not supported."); + } + + return new SimMetricsMatcher(matcher.Pattern, type); + + default: + throw new NotSupportedException($"Matcher '{matcherName}' is not supported."); + } + } + } +} diff --git a/src/WireMock.Net/Server/FluentMockServer.Admin.cs b/src/WireMock.Net/Server/FluentMockServer.Admin.cs index 9acb25e1..b622b225 100644 --- a/src/WireMock.Net/Server/FluentMockServer.Admin.cs +++ b/src/WireMock.Net/Server/FluentMockServer.Admin.cs @@ -607,7 +607,7 @@ namespace WireMock.Server var clientIPModel = JsonUtils.ParseJTokenToObject(requestModel.ClientIP); if (clientIPModel?.Matchers != null) { - requestBuilder = requestBuilder.WithPath(clientIPModel.Matchers.Select(MappingConverter.Map).Cast().ToArray()); + requestBuilder = requestBuilder.WithPath(clientIPModel.Matchers.Select(MatcherModelMapper.Map).Cast().ToArray()); } } } @@ -624,7 +624,7 @@ namespace WireMock.Server var pathModel = JsonUtils.ParseJTokenToObject(requestModel.Path); if (pathModel?.Matchers != null) { - requestBuilder = requestBuilder.WithPath(pathModel.Matchers.Select(MappingConverter.Map).Cast().ToArray()); + requestBuilder = requestBuilder.WithPath(pathModel.Matchers.Select(MatcherModelMapper.Map).Cast().ToArray()); } } } @@ -641,7 +641,7 @@ namespace WireMock.Server var urlModel = JsonUtils.ParseJTokenToObject(requestModel.Url); if (urlModel?.Matchers != null) { - requestBuilder = requestBuilder.WithUrl(urlModel.Matchers.Select(MappingConverter.Map).Cast().ToArray()); + requestBuilder = requestBuilder.WithUrl(urlModel.Matchers.Select(MatcherModelMapper.Map).Cast().ToArray()); } } } @@ -655,7 +655,7 @@ namespace WireMock.Server { foreach (var headerModel in requestModel.Headers.Where(h => h.Matchers != null)) { - requestBuilder = requestBuilder.WithHeader(headerModel.Name, headerModel.Matchers.Select(MappingConverter.Map).Cast().ToArray()); + requestBuilder = requestBuilder.WithHeader(headerModel.Name, headerModel.Matchers.Select(MatcherModelMapper.Map).Cast().ToArray()); } } @@ -663,21 +663,21 @@ namespace WireMock.Server { foreach (var cookieModel in requestModel.Cookies.Where(c => c.Matchers != null)) { - requestBuilder = requestBuilder.WithCookie(cookieModel.Name, cookieModel.Matchers.Select(MappingConverter.Map).Cast().ToArray()); + requestBuilder = requestBuilder.WithCookie(cookieModel.Name, cookieModel.Matchers.Select(MatcherModelMapper.Map).Cast().ToArray()); } } if (requestModel.Params != null) { - foreach (var paramModel in requestModel.Params.Where(p => p.Values != null)) + foreach (var paramModel in requestModel.Params) { - requestBuilder = requestBuilder.WithParam(paramModel.Name, paramModel.Values.ToArray()); + requestBuilder = paramModel.Values == null ? requestBuilder.WithParam(paramModel.Name) : requestBuilder.WithParam(paramModel.Name, paramModel.Values.ToArray()); } } if (requestModel.Body?.Matcher != null) { - var bodyMatcher = MappingConverter.Map(requestModel.Body.Matcher); + var bodyMatcher = MatcherModelMapper.Map(requestModel.Body.Matcher); requestBuilder = requestBuilder.WithBody(bodyMatcher); } diff --git a/src/WireMock.Net/WireMock.Net.csproj b/src/WireMock.Net/WireMock.Net.csproj index ff769002..2e47dd12 100644 --- a/src/WireMock.Net/WireMock.Net.csproj +++ b/src/WireMock.Net/WireMock.Net.csproj @@ -32,6 +32,10 @@ NETSTANDARD + + + + diff --git a/test/WireMock.Net.Tests/Matchers/ExactMatcherTests.cs b/test/WireMock.Net.Tests/Matchers/ExactMatcherTests.cs new file mode 100644 index 00000000..1cffc9bd --- /dev/null +++ b/test/WireMock.Net.Tests/Matchers/ExactMatcherTests.cs @@ -0,0 +1,61 @@ +using NFluent; +using WireMock.Matchers; +using Xunit; + +namespace WireMock.Net.Tests.Matchers +{ + public class ExactMatcherTests + { + [Fact] + public void ExactMatcher_GetName() + { + // Assign + var matcher = new ExactMatcher("X"); + + // Act + string name = matcher.GetName(); + + // Assert + Check.That(name).Equals("ExactMatcher"); + } + + [Fact] + public void ExactMatcher_GetPatterns() + { + // Assign + var matcher = new ExactMatcher("X"); + + // Act + string[] patterns = matcher.GetPatterns(); + + // Assert + Check.That(patterns).ContainsExactly("X"); + } + + [Fact] + public void ExactMatcher_IsMatch_MultiplePatterns() + { + // Assign + var matcher = new ExactMatcher("x", "y"); + + // Act + double result = matcher.IsMatch("x"); + + // Assert + Check.That(result).IsEqualTo(0.5d); + } + + [Fact] + public void Request_WithBodyExactMatcher_false() + { + // Assign + var matcher = new ExactMatcher("cat"); + + // Act + double result = matcher.IsMatch("caR"); + + // Assert + Check.That(result).IsStrictlyLessThan(1.0); + } + } +} \ No newline at end of file diff --git a/test/WireMock.Net.Tests/Matchers/RegexMatcherTests.cs b/test/WireMock.Net.Tests/Matchers/RegexMatcherTests.cs new file mode 100644 index 00000000..0c1446f4 --- /dev/null +++ b/test/WireMock.Net.Tests/Matchers/RegexMatcherTests.cs @@ -0,0 +1,74 @@ +using NFluent; +using WireMock.Matchers; +using Xunit; + +namespace WireMock.Net.Tests.Matchers +{ + public class RegexMatcherTests + { + [Fact] + public void RegexMatcher_GetName() + { + // Assign + var matcher = new RegexMatcher(""); + + // Act + string name = matcher.GetName(); + + // Assert + Check.That(name).Equals("RegexMatcher"); + } + + [Fact] + public void RegexMatcher_GetPatterns() + { + // Assign + var matcher = new RegexMatcher("X"); + + // Act + string[] patterns = matcher.GetPatterns(); + + // Assert + Check.That(patterns).ContainsExactly("X"); + } + + [Fact] + public void RegexMatcher_IsMatch() + { + // Assign + var matcher = new RegexMatcher("H.*o"); + + // Act + double result = matcher.IsMatch("Hello world!"); + + // Assert + Check.That(result).IsEqualTo(1.0d); + } + + [Fact] + public void RegexMatcher_IsMatch_NullInput() + { + // Assign + var matcher = new RegexMatcher("H.*o"); + + // Act + double result = matcher.IsMatch(null); + + // Assert + Check.That(result).IsEqualTo(0.0d); + } + + [Fact] + public void RegexMatcher_IsMatch_IgnoreCase() + { + // Assign + var matcher = new RegexMatcher("H.*o", true); + + // Act + double result = matcher.IsMatch("hello world!"); + + // Assert + Check.That(result).IsEqualTo(1.0d); + } + } +} \ No newline at end of file diff --git a/test/WireMock.Net.Tests/Matchers/SimMetricsMatcherTests.cs b/test/WireMock.Net.Tests/Matchers/SimMetricsMatcherTests.cs new file mode 100644 index 00000000..bc7a9a57 --- /dev/null +++ b/test/WireMock.Net.Tests/Matchers/SimMetricsMatcherTests.cs @@ -0,0 +1,61 @@ +using NFluent; +using WireMock.Matchers; +using Xunit; + +namespace WireMock.Net.Tests.Matchers +{ + public class SimMetricsMatcherTests + { + [Fact] + public void SimMetricsMatcher_GetName() + { + // Assign + var matcher = new SimMetricsMatcher("X"); + + // Act + string name = matcher.GetName(); + + // Assert + Check.That(name).Equals("SimMetricsMatcher.Levenstein"); + } + + [Fact] + public void SimMetricsMatcher_GetPatterns() + { + // Assign + var matcher = new SimMetricsMatcher("X"); + + // Act + string[] patterns = matcher.GetPatterns(); + + // Assert + Check.That(patterns).ContainsExactly("X"); + } + + [Fact] + public void SimMetricsMatcher_IsMatch_1() + { + // Assign + var matcher = new SimMetricsMatcher("The cat walks in the street."); + + // Act + double result = matcher.IsMatch("The car drives in the street."); + + // Assert + Check.That(result).IsStrictlyLessThan(1.0).And.IsStrictlyGreaterThan(0.5); + } + + [Fact] + public void SimMetricsMatcher_IsMatch_2() + { + // Assign + var matcher = new SimMetricsMatcher("The cat walks in the street."); + + // Act + double result = matcher.IsMatch("Hello"); + + // Assert + Check.That(result).IsStrictlyLessThan(0.1).And.IsStrictlyGreaterThan(0.05); + } + } +} \ No newline at end of file diff --git a/test/WireMock.Net.Tests/Matchers/WildcardMatcherTest.cs b/test/WireMock.Net.Tests/Matchers/WildcardMatcherTest.cs new file mode 100644 index 00000000..c399db14 --- /dev/null +++ b/test/WireMock.Net.Tests/Matchers/WildcardMatcherTest.cs @@ -0,0 +1,87 @@ +using NFluent; +using WireMock.Matchers; +using Xunit; + +namespace WireMock.Net.Tests.Matchers +{ + public class WildcardMatcherTest + { + [Fact] + public void WildcardMatcher_IsMatch_Positive() + { + var tests = new[] + { + new {p = "*", i = ""}, + new {p = "?", i = " "}, + new {p = "*", i = "a"}, + new {p = "*", i = "ab"}, + new {p = "?", i = "a"}, + new {p = "*?", i = "abc"}, + new {p = "?*", i = "abc"}, + new {p = "abc", i = "abc"}, + new {p = "abc*", i = "abc"}, + new {p = "abc*", i = "abcd"}, + new {p = "*abc*", i = "abc"}, + new {p = "*a*bc*", i = "abc"}, + new {p = "*a*b?", i = "aXXXbc"} + }; + + foreach (var test in tests) + { + var matcher = new WildcardMatcher(test.p); + Check.That(matcher.IsMatch(test.i)).IsEqualTo(1.0d); + } + } + + [Fact] + public void WildcardMatcher_IsMatch_Negative() + { + var tests = new[] + { + new {p = "*a", i = ""}, + new {p = "a*", i = ""}, + new {p = "?", i = ""}, + new {p = "*b*", i = "a"}, + new {p = "b*a", i = "ab"}, + new {p = "??", i = "a"}, + new {p = "*?", i = ""}, + new {p = "??*", i = "a"}, + new {p = "*abc", i = "abX"}, + new {p = "*abc*", i = "Xbc"}, + new {p = "*a*bc*", i = "ac"} + }; + + foreach (var test in tests) + { + var matcher = new WildcardMatcher(test.p); + Check.That(matcher.IsMatch(test.i)).IsEqualTo(0.0); + } + } + + [Fact] + public void WildcardMatcher_GetName() + { + // Assign + var matcher = new WildcardMatcher("x"); + + // Act + string name = matcher.GetName(); + + // Assert + Check.That(name).Equals("WildcardMatcher"); + } + + [Fact] + public void WildcardMatcher_GetPatterns() + { + // Assign + var matcher = new WildcardMatcher("x"); + + // Act + string[] patterns = matcher.GetPatterns(); + + // Assert + Check.That(patterns).ContainsExactly("x"); + } + } +} \ No newline at end of file diff --git a/test/WireMock.Net.Tests/RequestMatchers/RequestMessageCompositeMatcherTests.cs b/test/WireMock.Net.Tests/RequestMatchers/RequestMessageCompositeMatcherTests.cs new file mode 100644 index 00000000..3a51f36d --- /dev/null +++ b/test/WireMock.Net.Tests/RequestMatchers/RequestMessageCompositeMatcherTests.cs @@ -0,0 +1,83 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Moq; +using NFluent; +using WireMock.Matchers.Request; +using Xunit; + +namespace WireMock.Net.Tests.RequestMatchers +{ + public class RequestMessageCompositeMatcherTests + { + private class Helper : RequestMessageCompositeMatcher + { + public Helper(IEnumerable requestMatchers, CompositeMatcherType type = CompositeMatcherType.And) : base(requestMatchers, type) + { + } + } + + [Fact] + public void RequestMessageCompositeMatcher_GetMatchingScore_EmptyArray() + { + // Assign + var requestMessage = new RequestMessage(new Uri("http://localhost"), "GET", "127.0.0.1"); + var matcher = new Helper(Enumerable.Empty()); + + // Act + var result = new RequestMatchResult(); + double score = matcher.GetMatchingScore(requestMessage, result); + + // Assert + Check.That(score).IsEqualTo(0.0d); + } + + [Fact] + public void RequestMessageCompositeMatcher_GetMatchingScore_CompositeMatcherType_And() + { + // Assign + var requestMatcher1Mock = new Mock(); + requestMatcher1Mock.Setup(rm => rm.GetMatchingScore(It.IsAny(), It.IsAny())).Returns(1.0d); + var requestMatcher2Mock = new Mock(); + requestMatcher2Mock.Setup(rm => rm.GetMatchingScore(It.IsAny(), It.IsAny())).Returns(0.8d); + + var requestMessage = new RequestMessage(new Uri("http://localhost"), "GET", "127.0.0.1"); + var matcher = new Helper(new[] { requestMatcher1Mock.Object, requestMatcher2Mock.Object }); + + // Act + var result = new RequestMatchResult(); + double score = matcher.GetMatchingScore(requestMessage, result); + + // Assert + Check.That(score).IsEqualTo(0.9d); + + // Verify + requestMatcher1Mock.Verify(rm => rm.GetMatchingScore(It.IsAny(), It.IsAny()), Times.Once); + requestMatcher2Mock.Verify(rm => rm.GetMatchingScore(It.IsAny(), It.IsAny()), Times.Once); + } + + [Fact] + public void RequestMessageCompositeMatcher_GetMatchingScore_CompositeMatcherType_Or() + { + // Assign + var requestMatcher1Mock = new Mock(); + requestMatcher1Mock.Setup(rm => rm.GetMatchingScore(It.IsAny(), It.IsAny())).Returns(1.0d); + var requestMatcher2Mock = new Mock(); + requestMatcher2Mock.Setup(rm => rm.GetMatchingScore(It.IsAny(), It.IsAny())).Returns(0.8d); + + var requestMessage = new RequestMessage(new Uri("http://localhost"), "GET", "127.0.0.1"); + var matcher = new Helper(new[] { requestMatcher1Mock.Object, requestMatcher2Mock.Object }, CompositeMatcherType.Or); + + // Act + var result = new RequestMatchResult(); + double score = matcher.GetMatchingScore(requestMessage, result); + + // Assert + Check.That(score).IsEqualTo(1.0d); + + // Verify + requestMatcher1Mock.Verify(rm => rm.GetMatchingScore(It.IsAny(), It.IsAny()), Times.Once); + requestMatcher2Mock.Verify(rm => rm.GetMatchingScore(It.IsAny(), It.IsAny()), Times.Once); + } + } +} diff --git a/test/WireMock.Net.Tests/RequestMatchers/RequestMessageCookieMatcherTests.cs b/test/WireMock.Net.Tests/RequestMatchers/RequestMessageCookieMatcherTests.cs new file mode 100644 index 00000000..97335b50 --- /dev/null +++ b/test/WireMock.Net.Tests/RequestMatchers/RequestMessageCookieMatcherTests.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using NFluent; +using WireMock.Matchers; +using WireMock.Matchers.Request; +using Xunit; + +namespace WireMock.Net.Tests.RequestMatchers +{ + public class RequestMessageCookieMatcherTests + { + [Fact] + public void RequestMessageCookieMatcher_GetMatchingScore_IStringMatcher_Match() + { + // Assign + var cookies = new Dictionary { { "cook", "x" } }; + var requestMessage = new RequestMessage(new Uri("http://localhost"), "GET", "127.0.0.1", null, null, cookies); + var matcher = new RequestMessageCookieMatcher("cook", new ExactMatcher("x")); + + // Act + var result = new RequestMatchResult(); + double score = matcher.GetMatchingScore(requestMessage, result); + + // Assert + Check.That(score).IsEqualTo(1.0d); + } + + [Fact] + public void RequestMessageCookieMatcher_GetMatchingScore_Func_Match() + { + // Assign + var cookies = new Dictionary { { "cook", "x" } }; + var requestMessage = new RequestMessage(new Uri("http://localhost"), "GET", "127.0.0.1", null, null, cookies); + var matcher = new RequestMessageCookieMatcher(x => x.ContainsKey("cook")); + + // Act + var result = new RequestMatchResult(); + double score = matcher.GetMatchingScore(requestMessage, result); + + // Assert + Check.That(score).IsEqualTo(1.0d); + } + } +} \ No newline at end of file diff --git a/test/WireMock.Net.Tests/RequestMatchers/RequestMessageHeaderMatcherTests.cs b/test/WireMock.Net.Tests/RequestMatchers/RequestMessageHeaderMatcherTests.cs new file mode 100644 index 00000000..c273a882 --- /dev/null +++ b/test/WireMock.Net.Tests/RequestMatchers/RequestMessageHeaderMatcherTests.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using NFluent; +using WireMock.Matchers; +using WireMock.Matchers.Request; +using Xunit; + +namespace WireMock.Net.Tests.RequestMatchers +{ + public class RequestMessageHeaderMatcherTests + { + [Fact] + public void RequestMessageHeaderMatcher_GetMatchingScore_IStringMatcher_Match() + { + // Assign + var headers = new Dictionary { { "h", new [] { "x" } } }; + var requestMessage = new RequestMessage(new Uri("http://localhost"), "GET", "127.0.0.1", null, headers); + var matcher = new RequestMessageHeaderMatcher("h", new ExactMatcher("x")); + + // Act + var result = new RequestMatchResult(); + double score = matcher.GetMatchingScore(requestMessage, result); + + // Assert + Check.That(score).IsEqualTo(1.0d); + } + + [Fact] + public void RequestMessageHeaderMatcher_GetMatchingScore_Func_Match() + { + // Assign + var headers = new Dictionary { { "h", new[] { "x" } } }; + var requestMessage = new RequestMessage(new Uri("http://localhost"), "GET", "127.0.0.1", null, headers); + var matcher = new RequestMessageHeaderMatcher(x => x.ContainsKey("h")); + + // Act + var result = new RequestMatchResult(); + double score = matcher.GetMatchingScore(requestMessage, result); + + // Assert + Check.That(score).IsEqualTo(1.0d); + } + } +} \ No newline at end of file diff --git a/test/WireMock.Net.Tests/RequestWithBodyTests.cs b/test/WireMock.Net.Tests/RequestWithBodyTests.cs index c773b5b9..90453a08 100644 --- a/test/WireMock.Net.Tests/RequestWithBodyTests.cs +++ b/test/WireMock.Net.Tests/RequestWithBodyTests.cs @@ -85,70 +85,6 @@ namespace WireMock.Net.Tests Check.That(requestBuilder.GetMatchingScore(request, requestMatchResult)).IsEqualTo(1.0); } - [Fact] - public void Request_WithBodyExactMatcher_multiplePatterns() - { - // given - var requestBuilder = Request.Create().UsingAnyVerb().WithBody(new ExactMatcher("cat", "dog")); - - // when - string bodyAsString = "cat"; - byte[] body = Encoding.UTF8.GetBytes(bodyAsString); - var request = new RequestMessage(new Uri("http://localhost/foo"), "POST", ClientIp, body, bodyAsString, Encoding.UTF8); - - // then - var requestMatchResult = new RequestMatchResult(); - Check.That(requestBuilder.GetMatchingScore(request, requestMatchResult)).IsEqualTo(0.5); - } - - [Fact] - public void Request_WithBodyExactMatcher_false() - { - // given - var requestBuilder = Request.Create().UsingAnyVerb().WithBody(new ExactMatcher("cat")); - - // when - string bodyAsString = "caR"; - byte[] body = Encoding.UTF8.GetBytes(bodyAsString); - var request = new RequestMessage(new Uri("http://localhost/foo"), "POST", ClientIp, body, bodyAsString, Encoding.UTF8); - - // then - var requestMatchResult = new RequestMatchResult(); - Check.That(requestBuilder.GetMatchingScore(request, requestMatchResult)).IsStrictlyLessThan(1.0); - } - - [Fact] - public void Request_WithBodySimMetricsMatcher1() - { - // given - var requestBuilder = Request.Create().UsingAnyVerb().WithBody(new SimMetricsMatcher("The cat walks in the street.")); - - // when - string bodyAsString = "The car drives in the street."; - byte[] body = Encoding.UTF8.GetBytes(bodyAsString); - var request = new RequestMessage(new Uri("http://localhost/foo"), "POST", ClientIp, body, bodyAsString, Encoding.UTF8); - - // then - var requestMatchResult = new RequestMatchResult(); - Check.That(requestBuilder.GetMatchingScore(request, requestMatchResult)).IsStrictlyLessThan(1.0).And.IsStrictlyGreaterThan(0.5); - } - - [Fact] - public void Request_WithBodySimMetricsMatcher2() - { - // given - var requestBuilder = Request.Create().UsingAnyVerb().WithBody(new SimMetricsMatcher("The cat walks in the street.")); - - // when - string bodyAsString = "Hello"; - byte[] body = Encoding.UTF8.GetBytes(bodyAsString); - var request = new RequestMessage(new Uri("http://localhost/foo"), "POST", ClientIp, body, bodyAsString, Encoding.UTF8); - - // then - var requestMatchResult = new RequestMatchResult(); - Check.That(requestBuilder.GetMatchingScore(request, requestMatchResult)).IsStrictlyLessThan(0.1).And.IsStrictlyGreaterThan(0.05); - } - [Fact] public void Request_WithBodyWildcardMatcher() { @@ -165,22 +101,6 @@ namespace WireMock.Net.Tests Check.That(spec.GetMatchingScore(request, requestMatchResult)).IsEqualTo(1.0); } - [Fact] - public void Request_WithBodyRegexMatcher() - { - // given - var spec = Request.Create().UsingAnyVerb().WithBody(new RegexMatcher("H.*o")); - - // when - string bodyAsString = "Hello world!"; - byte[] body = Encoding.UTF8.GetBytes(bodyAsString); - var request = new RequestMessage(new Uri("http://localhost/foo"), "PUT", ClientIp, body, bodyAsString, Encoding.UTF8); - - // then - var requestMatchResult = new RequestMatchResult(); - Check.That(spec.GetMatchingScore(request, requestMatchResult)).IsEqualTo(1.0); - } - [Fact] public void Request_WithBodyXPathMatcher_true() { diff --git a/test/WireMock.Net.Tests/ResponseWithBodyHandlebarsTests.cs b/test/WireMock.Net.Tests/ResponseBuilderTests/ResponseWithBodyHandlebarsTests.cs similarity index 99% rename from test/WireMock.Net.Tests/ResponseWithBodyHandlebarsTests.cs rename to test/WireMock.Net.Tests/ResponseBuilderTests/ResponseWithBodyHandlebarsTests.cs index 70840fe0..91f18d16 100644 --- a/test/WireMock.Net.Tests/ResponseWithBodyHandlebarsTests.cs +++ b/test/WireMock.Net.Tests/ResponseBuilderTests/ResponseWithBodyHandlebarsTests.cs @@ -8,7 +8,7 @@ using WireMock.ResponseBuilders; using WireMock.Util; using Xunit; -namespace WireMock.Net.Tests +namespace WireMock.Net.Tests.ResponseBuilderTests { public class ResponseWithBodyHandlebarsTests { diff --git a/test/WireMock.Net.Tests/ResponseWithBodyTests.cs b/test/WireMock.Net.Tests/ResponseBuilderTests/ResponseWithBodyTests.cs similarity index 60% rename from test/WireMock.Net.Tests/ResponseWithBodyTests.cs rename to test/WireMock.Net.Tests/ResponseBuilderTests/ResponseWithBodyTests.cs index d3d7e85e..6dd95a3e 100644 --- a/test/WireMock.Net.Tests/ResponseWithBodyTests.cs +++ b/test/WireMock.Net.Tests/ResponseBuilderTests/ResponseWithBodyTests.cs @@ -3,9 +3,10 @@ using System.Text; using System.Threading.Tasks; using NFluent; using WireMock.ResponseBuilders; +using WireMock.Util; using Xunit; -namespace WireMock.Net.Tests +namespace WireMock.Net.Tests.ResponseBuilderTests { public class ResponseWithBodyTests { @@ -86,5 +87,59 @@ namespace WireMock.Net.Tests Check.That(responseMessage.BodyAsJson).Equals(x); Check.That(responseMessage.BodyEncoding).Equals(Encoding.ASCII); } + + [Fact] + public async Task Response_ProvideResponse_WithBody_String_SameAsSource_Encoding() + { + // Assign + var request = new RequestMessage(new Uri("http://localhost"), "GET", ClientIp); + + var response = Response.Create().WithBody("r", BodyDestinationFormat.SameAsSource, Encoding.ASCII); + + // Act + var responseMessage = await response.ProvideResponseAsync(request); + + // Assert + Check.That(responseMessage.BodyAsBytes).IsNull(); + Check.That(responseMessage.BodyAsJson).IsNull(); + Check.That(responseMessage.Body).Equals("r"); + Check.That(responseMessage.BodyEncoding).Equals(Encoding.ASCII); + } + + [Fact] + public async Task Response_ProvideResponse_WithBody_String_Bytes_Encoding() + { + // Assign + var request = new RequestMessage(new Uri("http://localhost"), "GET", ClientIp); + + var response = Response.Create().WithBody("r", BodyDestinationFormat.Bytes, Encoding.ASCII); + + // Act + var responseMessage = await response.ProvideResponseAsync(request); + + // Assert + Check.That(responseMessage.Body).IsNull(); + Check.That(responseMessage.BodyAsJson).IsNull(); + Check.That(responseMessage.BodyAsBytes).IsNotNull(); + Check.That(responseMessage.BodyEncoding).Equals(Encoding.ASCII); + } + + [Fact] + public async Task Response_ProvideResponse_WithBody_String_Json_Encoding() + { + // Assign + var request = new RequestMessage(new Uri("http://localhost"), "GET", ClientIp); + + var response = Response.Create().WithBody("{ \"value\": 42 }", BodyDestinationFormat.Json, Encoding.ASCII); + + // Act + var responseMessage = await response.ProvideResponseAsync(request); + + // Assert + Check.That(responseMessage.Body).IsNull(); + Check.That(responseMessage.BodyAsBytes).IsNull(); + Check.That(((dynamic) responseMessage.BodyAsJson).value).Equals(42); + Check.That(responseMessage.BodyEncoding).Equals(Encoding.ASCII); + } } } \ No newline at end of file diff --git a/test/WireMock.Net.Tests/ResponseBuilderTests/ResponseWithHeadersTests.cs b/test/WireMock.Net.Tests/ResponseBuilderTests/ResponseWithHeadersTests.cs new file mode 100644 index 00000000..2c353185 --- /dev/null +++ b/test/WireMock.Net.Tests/ResponseBuilderTests/ResponseWithHeadersTests.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using NFluent; +using WireMock.ResponseBuilders; +using WireMock.Util; +using Xunit; + +namespace WireMock.Net.Tests.ResponseBuilderTests +{ + public class ResponseWithHeadersTests + { + private const string ClientIp = "::1"; + + [Fact] + public async Task Response_ProvideResponse_WithHeaders_SingleValue() + { + // Assign + var request = new RequestMessage(new Uri("http://localhost"), "GET", ClientIp); + var headers = new Dictionary { { "h", "x" } }; + var response = Response.Create().WithHeaders(headers); + + // Act + var responseMessage = await response.ProvideResponseAsync(request); + + // Assert + Check.That(responseMessage.Headers["h"]).ContainsExactly("x"); + } + + [Fact] + public async Task Response_ProvideResponse_WithHeaders_MultipleValues() + { + // Assign + var request = new RequestMessage(new Uri("http://localhost"), "GET", ClientIp); + var headers = new Dictionary { { "h", new[] { "x" } } }; + var response = Response.Create().WithHeaders(headers); + + // Act + var responseMessage = await response.ProvideResponseAsync(request); + + // Assert + Check.That(responseMessage.Headers["h"]).ContainsExactly("x"); + } + + [Fact] + public async Task Response_ProvideResponse_WithHeaders_WiremockList() + { + // Assign + var request = new RequestMessage(new Uri("http://localhost"), "GET", ClientIp); + var headers = new Dictionary> { { "h", new WireMockList("x") } }; + var response = Response.Create().WithHeaders(headers); + + // Act + var responseMessage = await response.ProvideResponseAsync(request); + + // Assert + Check.That(responseMessage.Headers["h"]).ContainsExactly("x"); + } + } +} \ No newline at end of file diff --git a/test/WireMock.Net.Tests/Serialization/MatcherModelMapperTests.cs b/test/WireMock.Net.Tests/Serialization/MatcherModelMapperTests.cs new file mode 100644 index 00000000..260fcaef --- /dev/null +++ b/test/WireMock.Net.Tests/Serialization/MatcherModelMapperTests.cs @@ -0,0 +1,156 @@ +using System; +using NFluent; +using WireMock.Admin.Mappings; +using WireMock.Matchers; +using WireMock.Serialization; +using Xunit; + +namespace WireMock.Net.Tests.Serialization +{ + public class MatcherModelMapperTests + { + [Fact] + public void MatcherModelMapper_Map_Null() + { + // Act + IMatcher matcher = MatcherModelMapper.Map(null); + + // Assert + Check.That(matcher).IsNull(); + } + + [Fact] + public void MatcherModelMapper_Map_ExactMatcher_Pattern() + { + // Assign + var model = new MatcherModel + { + Name = "ExactMatcher", + Patterns = new[] { "x" } + }; + + // Act + var matcher = (ExactMatcher)MatcherModelMapper.Map(model); + + // Assert + Check.That(matcher.GetPatterns()).ContainsExactly("x"); + } + + [Fact] + public void MatcherModelMapper_Map_ExactMatcher_Patterns() + { + // Assign + var model = new MatcherModel + { + Name = "ExactMatcher", + Patterns = new[] { "x", "y" } + }; + + // Act + var matcher = (ExactMatcher)MatcherModelMapper.Map(model); + + // Assert + Check.That(matcher.GetPatterns()).ContainsExactly("x", "y"); + } + + [Fact] + public void MatcherModelMapper_Map_RegexMatcher() + { + // Assign + var model = new MatcherModel + { + Name = "RegexMatcher", + Patterns = new[] { "x", "y" }, + IgnoreCase = true + }; + + // Act + var matcher = (RegexMatcher)MatcherModelMapper.Map(model); + + // Assert + Check.That(matcher.GetPatterns()).ContainsExactly("x", "y"); + Check.That(matcher.IsMatch("X")).IsEqualTo(0.5d); + } + + [Fact] + public void MatcherModelMapper_Map_WildcardMatcher() + { + // Assign + var model = new MatcherModel + { + Name = "WildcardMatcher", + Patterns = new[] { "x", "y" }, + IgnoreCase = true + }; + + // Act + var matcher = (WildcardMatcher)MatcherModelMapper.Map(model); + + // Assert + Check.That(matcher.GetPatterns()).ContainsExactly("x", "y"); + Check.That(matcher.IsMatch("X")).IsEqualTo(0.5d); + } + + [Fact] + public void MatcherModelMapper_Map_SimMetricsMatcher() + { + // Assign + var model = new MatcherModel + { + Name = "SimMetricsMatcher", + Pattern = "x" + }; + + // Act + var matcher = (SimMetricsMatcher)MatcherModelMapper.Map(model); + + // Assert + Check.That(matcher.GetPatterns()).ContainsExactly("x"); + } + + [Fact] + public void MatcherModelMapper_Map_SimMetricsMatcher_BlockDistance() + { + // Assign + var model = new MatcherModel + { + Name = "SimMetricsMatcher.BlockDistance", + Pattern = "x" + }; + + // Act + var matcher = (SimMetricsMatcher)MatcherModelMapper.Map(model); + + // Assert + Check.That(matcher.GetPatterns()).ContainsExactly("x"); + } + + [Fact] + public void MatcherModelMapper_Map_SimMetricsMatcher_Throws1() + { + // Assign + var model = new MatcherModel + { + Name = "error", + Pattern = "x" + }; + + // Act + Check.ThatCode(() => MatcherModelMapper.Map(model)).Throws(); + } + + [Fact] + public void MatcherModelMapper_Map_SimMetricsMatcher_Throws2() + { + // Assign + var model = new MatcherModel + { + Name = "SimMetricsMatcher.error", + Pattern = "x" + }; + + // Act + Check.ThatCode(() => MatcherModelMapper.Map(model)).Throws(); + } + } +} \ No newline at end of file diff --git a/test/WireMock.Net.Tests/WildcardMatcherTest.cs b/test/WireMock.Net.Tests/WildcardMatcherTest.cs deleted file mode 100644 index 8638e3b3..00000000 --- a/test/WireMock.Net.Tests/WildcardMatcherTest.cs +++ /dev/null @@ -1,64 +0,0 @@ -using NFluent; -using Xunit; -using WireMock.Matchers; - -namespace WireMock.Net.Tests -{ - //[TestFixture] - public class WildcardMatcherTest - { - [Fact] - public void WildcardMatcher_patterns_positive() - { - var tests = new[] - { - new { p = "*", i = "" }, - new { p = "?", i = " " }, - new { p = "*", i = "a" }, - new { p = "*", i = "ab" }, - new { p = "?", i = "a" }, - new { p = "*?", i = "abc" }, - new { p = "?*", i = "abc" }, - new { p = "abc", i = "abc" }, - new { p = "abc*", i = "abc" }, - new { p = "abc*", i = "abcd" }, - new { p = "*abc*", i = "abc" }, - new { p = "*a*bc*", i = "abc" }, - new { p = "*a*b?", i = "aXXXbc" } - }; - - foreach (var test in tests) - { - var matcher = new WildcardMatcher(test.p); - Check.That(matcher.IsMatch(test.i)).Equals(1.0); - //Assert.AreEqual(1.0, matcher.IsMatch(test.i), "p = " + test.p + ", i = " + test.i); - } - } - - [Fact] - public void WildcardMatcher_patterns_negative() - { - var tests = new[] - { - new { p = "*a", i = ""}, - new { p = "a*", i = ""}, - new { p = "?", i = ""}, - new { p = "*b*", i = "a"}, - new { p = "b*a", i = "ab"}, - new { p = "??", i = "a"}, - new { p = "*?", i = ""}, - new { p = "??*", i = "a"}, - new { p = "*abc", i = "abX"}, - new { p = "*abc*", i = "Xbc"}, - new { p = "*a*bc*", i = "ac"} - }; - - foreach (var test in tests) - { - var matcher = new WildcardMatcher(test.p); - //Assert.AreEqual(0.0, matcher.IsMatch(test.i), "p = " + test.p + ", i = " + test.i); - Check.That(matcher.IsMatch(test.i)).Equals(0.0); - } - } - } -} \ No newline at end of file