mirror of
https://github.com/wiremock/WireMock.Net.git
synced 2026-02-25 02:05:04 +01:00
@@ -1,19 +1,18 @@
|
||||
namespace WireMock.Admin.Mappings
|
||||
namespace WireMock.Admin.Mappings;
|
||||
|
||||
/// <summary>
|
||||
/// Fault Model
|
||||
/// </summary>
|
||||
[FluentBuilder.AutoGenerateBuilder]
|
||||
public class FaultModel
|
||||
{
|
||||
/// <summary>
|
||||
/// Fault Model
|
||||
/// Gets or sets the fault. Can be null, "", NONE, EMPTY_RESPONSE or MALFORMED_RESPONSE_CHUNK.
|
||||
/// </summary>
|
||||
[FluentBuilder.AutoGenerateBuilder]
|
||||
public class FaultModel
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the fault. Can be null, "", NONE, EMPTY_RESPONSE, MALFORMED_RESPONSE_CHUNK or RANDOM_DATA_THEN_CLOSE.
|
||||
/// </summary>
|
||||
public string Type { get; set; }
|
||||
public string? Type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the fault percentage.
|
||||
/// </summary>
|
||||
public double? Percentage { get; set; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets or sets the fault percentage.
|
||||
/// </summary>
|
||||
public double? Percentage { get; set; }
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using WireMock.Models;
|
||||
|
||||
namespace WireMock.Admin.Mappings;
|
||||
@@ -94,4 +93,9 @@ public class MappingModel
|
||||
/// </example>
|
||||
/// </summary>
|
||||
public object? Data { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The probability when this request should be matched. Value is between 0 and 1. [Optional]
|
||||
/// </summary>
|
||||
public double? Probability { get; set; }
|
||||
}
|
||||
@@ -1,23 +1,23 @@
|
||||
namespace WireMock.ResponseBuilders
|
||||
// ReSharper disable InconsistentNaming
|
||||
namespace WireMock.ResponseBuilders;
|
||||
|
||||
/// <summary>
|
||||
/// The FaultType enumeration
|
||||
/// </summary>
|
||||
public enum FaultType
|
||||
{
|
||||
/// <summary>
|
||||
/// The FaultType enumeration
|
||||
/// No Fault
|
||||
/// </summary>
|
||||
public enum FaultType
|
||||
{
|
||||
/// <summary>
|
||||
/// No Fault
|
||||
/// </summary>
|
||||
NONE,
|
||||
NONE,
|
||||
|
||||
/// <summary>
|
||||
/// Return a completely empty response.
|
||||
/// </summary>
|
||||
EMPTY_RESPONSE,
|
||||
/// <summary>
|
||||
/// Return a completely empty response.
|
||||
/// </summary>
|
||||
EMPTY_RESPONSE,
|
||||
|
||||
/// <summary>
|
||||
/// Send a defined status header, then garbage, then close the connection.
|
||||
/// </summary>
|
||||
MALFORMED_RESPONSE_CHUNK
|
||||
}
|
||||
/// <summary>
|
||||
/// Send a defined status header, then garbage, then close the connection.
|
||||
/// </summary>
|
||||
MALFORMED_RESPONSE_CHUNK
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using WireMock.Matchers.Request;
|
||||
using WireMock.Models;
|
||||
@@ -132,6 +131,11 @@ public interface IMapping
|
||||
/// </summary>
|
||||
object? Data { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The probability when this request should be matched. Value is between 0 and 1. [Optional]
|
||||
/// </summary>
|
||||
double? Probability { get; }
|
||||
|
||||
/// <summary>
|
||||
/// ProvideResponseAsync
|
||||
/// </summary>
|
||||
|
||||
@@ -4,7 +4,7 @@ using System.Linq.Dynamic.Core;
|
||||
|
||||
namespace WireMock.Json;
|
||||
|
||||
public class DynamicPropertyWithValue : DynamicProperty
|
||||
internal class DynamicPropertyWithValue : DynamicProperty
|
||||
{
|
||||
public object? Value { get; }
|
||||
|
||||
|
||||
@@ -75,6 +75,9 @@ public class Mapping : IMapping
|
||||
/// <inheritdoc />
|
||||
public object? Data { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public double? Probability { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Mapping"/> class.
|
||||
/// </summary>
|
||||
@@ -95,6 +98,7 @@ public class Mapping : IMapping
|
||||
/// <param name="useWebhooksFireAndForget">Use Fire and Forget for the defined webhook(s). [Optional]</param>
|
||||
/// <param name="timeSettings">The TimeSettings. [Optional]</param>
|
||||
/// <param name="data">The data object. [Optional]</param>
|
||||
/// <param name="probability">Define the probability when this request should be matched. [Optional]</param>
|
||||
public Mapping(
|
||||
Guid guid,
|
||||
DateTime updatedAt,
|
||||
@@ -112,7 +116,8 @@ public class Mapping : IMapping
|
||||
IWebhook[]? webhooks,
|
||||
bool? useWebhooksFireAndForget,
|
||||
ITimeSettings? timeSettings,
|
||||
object? data)
|
||||
object? data,
|
||||
double? probability)
|
||||
{
|
||||
Guid = guid;
|
||||
UpdatedAt = updatedAt;
|
||||
@@ -131,6 +136,7 @@ public class Mapping : IMapping
|
||||
UseWebhooksFireAndForget = useWebhooksFireAndForget;
|
||||
TimeSettings = timeSettings;
|
||||
Data = data;
|
||||
Probability = probability;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IMapping.ProvideResponseAsync" />
|
||||
|
||||
@@ -69,12 +69,7 @@ public class MappingBuilder : IMappingBuilder
|
||||
/// <inheritdoc />
|
||||
public MappingModel[] GetMappings()
|
||||
{
|
||||
return GetMappingsInternal().Select(_mappingConverter.ToMappingModel).ToArray();
|
||||
}
|
||||
|
||||
internal IMapping[] GetMappingsInternal()
|
||||
{
|
||||
return _options.Mappings.Values.ToArray().Where(m => !m.IsAdminInterface).ToArray();
|
||||
return GetNonAdminMappings().Select(_mappingConverter.ToMappingModel).ToArray();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -86,7 +81,7 @@ public class MappingBuilder : IMappingBuilder
|
||||
/// <inheritdoc />
|
||||
public string? ToCSharpCode(Guid guid, MappingConverterType converterType)
|
||||
{
|
||||
var mapping = GetMappingsInternal().FirstOrDefault(m => m.Guid == guid);
|
||||
var mapping = GetNonAdminMappings().FirstOrDefault(m => m.Guid == guid);
|
||||
if (mapping is null)
|
||||
{
|
||||
return null;
|
||||
@@ -101,7 +96,7 @@ public class MappingBuilder : IMappingBuilder
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
bool addStart = true;
|
||||
foreach (var mapping in GetMappingsInternal())
|
||||
foreach (var mapping in GetNonAdminMappings())
|
||||
{
|
||||
sb.AppendLine(_mappingConverter.ToCSharpCode(mapping, new MappingConverterSettings { AddStart = addStart, ConverterType = converterType }));
|
||||
|
||||
@@ -123,7 +118,7 @@ public class MappingBuilder : IMappingBuilder
|
||||
/// <inheritdoc />
|
||||
public void SaveMappingsToFolder(string? folder)
|
||||
{
|
||||
foreach (var mapping in GetNonAdminMappings().Where(m => !m.IsAdminInterface))
|
||||
foreach (var mapping in GetNonAdminMappings())
|
||||
{
|
||||
_mappingToFileSaver.SaveMappingToFile(mapping, folder);
|
||||
}
|
||||
@@ -131,7 +126,7 @@ public class MappingBuilder : IMappingBuilder
|
||||
|
||||
private IMapping[] GetNonAdminMappings()
|
||||
{
|
||||
return _options.Mappings.Values.ToArray();
|
||||
return _options.Mappings.Values.Where(m => !m.IsAdminInterface).OrderBy(m => m.UpdatedAt).ToArray();
|
||||
}
|
||||
|
||||
private void RegisterMapping(IMapping mapping, bool saveToFile)
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using JetBrains.Annotations;
|
||||
using Stef.Validation;
|
||||
|
||||
namespace WireMock.Matchers.Request;
|
||||
@@ -25,9 +24,9 @@ public abstract class RequestMessageCompositeMatcher : IRequestMatcher
|
||||
/// </summary>
|
||||
/// <param name="requestMatchers">The request matchers.</param>
|
||||
/// <param name="type">The CompositeMatcherType type (Defaults to 'And')</param>
|
||||
protected RequestMessageCompositeMatcher([NotNull] IEnumerable<IRequestMatcher> requestMatchers, CompositeMatcherType type = CompositeMatcherType.And)
|
||||
protected RequestMessageCompositeMatcher(IEnumerable<IRequestMatcher> requestMatchers, CompositeMatcherType type = CompositeMatcherType.And)
|
||||
{
|
||||
Guard.NotNull(requestMatchers, nameof(requestMatchers));
|
||||
Guard.NotNull(requestMatchers);
|
||||
|
||||
_type = type;
|
||||
RequestMatchers = requestMatchers;
|
||||
|
||||
@@ -11,6 +11,7 @@ using Microsoft.Extensions.DependencyInjection;
|
||||
using Stef.Validation;
|
||||
using WireMock.Logging;
|
||||
using WireMock.Owin.Mappers;
|
||||
using WireMock.Services;
|
||||
using WireMock.Util;
|
||||
|
||||
namespace WireMock.Owin
|
||||
@@ -66,6 +67,7 @@ namespace WireMock.Owin
|
||||
{
|
||||
services.AddSingleton(_wireMockMiddlewareOptions);
|
||||
services.AddSingleton<IMappingMatcher, MappingMatcher>();
|
||||
services.AddSingleton<IRandomizerDoubleBetween0And1, RandomizerDoubleBetween0And1>();
|
||||
services.AddSingleton<IOwinRequestMapper, OwinRequestMapper>();
|
||||
services.AddSingleton<IOwinResponseMapper, OwinResponseMapper>();
|
||||
|
||||
|
||||
@@ -62,11 +62,11 @@ namespace WireMock.Owin.Mappers
|
||||
switch (responseMessage.FaultType)
|
||||
{
|
||||
case FaultType.EMPTY_RESPONSE:
|
||||
bytes = IsFault(responseMessage) ? new byte[0] : GetNormalBody(responseMessage);
|
||||
bytes = IsFault(responseMessage) ? EmptyArray<byte>.Value : GetNormalBody(responseMessage);
|
||||
break;
|
||||
|
||||
case FaultType.MALFORMED_RESPONSE_CHUNK:
|
||||
bytes = GetNormalBody(responseMessage) ?? new byte[0];
|
||||
bytes = GetNormalBody(responseMessage) ?? EmptyArray<byte>.Value;
|
||||
if (IsFault(responseMessage))
|
||||
{
|
||||
bytes = bytes.Take(bytes.Length / 2).Union(_randomizerBytes.Generate()).ToArray();
|
||||
@@ -87,7 +87,7 @@ namespace WireMock.Owin.Mappers
|
||||
|
||||
case { } typeAsString when typeAsString == typeof(string):
|
||||
// Note: this case will also match on null
|
||||
int.TryParse(responseMessage.StatusCode as string, out int result);
|
||||
int.TryParse(responseMessage.StatusCode as string, out var result);
|
||||
response.StatusCode = MapStatusCode(result);
|
||||
break;
|
||||
|
||||
|
||||
@@ -1,18 +1,21 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using WireMock.Extensions;
|
||||
using Stef.Validation;
|
||||
using WireMock.Extensions;
|
||||
using WireMock.Services;
|
||||
|
||||
namespace WireMock.Owin;
|
||||
|
||||
internal class MappingMatcher : IMappingMatcher
|
||||
{
|
||||
private readonly IWireMockMiddlewareOptions _options;
|
||||
private readonly IRandomizerDoubleBetween0And1 _randomizerDoubleBetween0And1;
|
||||
|
||||
public MappingMatcher(IWireMockMiddlewareOptions options)
|
||||
public MappingMatcher(IWireMockMiddlewareOptions options, IRandomizerDoubleBetween0And1 randomizerDoubleBetween0And1)
|
||||
{
|
||||
_options = Guard.NotNull(options);
|
||||
_randomizerDoubleBetween0And1 = Guard.NotNull(randomizerDoubleBetween0And1);
|
||||
}
|
||||
|
||||
public (MappingMatcherResult? Match, MappingMatcherResult? Partial) FindBestMatch(RequestMessage request)
|
||||
@@ -21,7 +24,12 @@ internal class MappingMatcher : IMappingMatcher
|
||||
|
||||
var possibleMappings = new List<MappingMatcherResult>();
|
||||
|
||||
foreach (var mapping in _options.Mappings.Values.Where(m => m.TimeSettings.IsValid()))
|
||||
var mappings = _options.Mappings.Values
|
||||
.Where(m => m.TimeSettings.IsValid())
|
||||
.Where(m => m.Probability is null || m.Probability <= _randomizerDoubleBetween0And1.Generate())
|
||||
.ToArray();
|
||||
|
||||
foreach (var mapping in mappings)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
@@ -9,6 +9,9 @@ using JetBrains.Annotations;
|
||||
using WireMock.Logging;
|
||||
using WireMock.Owin.Mappers;
|
||||
using Stef.Validation;
|
||||
using RandomDataGenerator.FieldOptions;
|
||||
using RandomDataGenerator.Randomizers;
|
||||
using WireMock.Services;
|
||||
|
||||
namespace WireMock.Owin;
|
||||
|
||||
@@ -70,7 +73,7 @@ internal class OwinSelfHost : IOwinSelfHost
|
||||
{
|
||||
var requestMapper = new OwinRequestMapper();
|
||||
var responseMapper = new OwinResponseMapper(_options);
|
||||
var matcher = new MappingMatcher(_options);
|
||||
var matcher = new MappingMatcher(_options, new RandomizerDoubleBetween0And1());
|
||||
|
||||
Action<IAppBuilder> startup = app =>
|
||||
{
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
namespace WireMock.RequestBuilders
|
||||
namespace WireMock.RequestBuilders;
|
||||
|
||||
/// <summary>
|
||||
/// IRequestBuilder
|
||||
/// </summary>
|
||||
public interface IRequestBuilder : IClientIPRequestBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// IRequestBuilder
|
||||
/// </summary>
|
||||
public interface IRequestBuilder : IClientIPRequestBuilder
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -1,82 +1,81 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using WireMock.Matchers;
|
||||
using WireMock.Matchers.Request;
|
||||
using Stef.Validation;
|
||||
|
||||
namespace WireMock.RequestBuilders
|
||||
namespace WireMock.RequestBuilders;
|
||||
|
||||
public partial class Request
|
||||
{
|
||||
public partial class Request
|
||||
/// <inheritdoc cref="ICookiesRequestBuilder.WithCookie(string, string, MatchBehaviour)"/>
|
||||
public IRequestBuilder WithCookie(string name, string pattern, MatchBehaviour matchBehaviour)
|
||||
{
|
||||
/// <inheritdoc cref="ICookiesRequestBuilder.WithCookie(string, string, MatchBehaviour)"/>
|
||||
public IRequestBuilder WithCookie(string name, string pattern, MatchBehaviour matchBehaviour)
|
||||
{
|
||||
return WithCookie(name, pattern, true, matchBehaviour);
|
||||
}
|
||||
return WithCookie(name, pattern, true, matchBehaviour);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="ICookiesRequestBuilder.WithCookie(string, string, bool, MatchBehaviour)"/>
|
||||
public IRequestBuilder WithCookie(string name, string pattern, bool ignoreCase = true, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
|
||||
{
|
||||
Guard.NotNull(name, nameof(name));
|
||||
Guard.NotNull(pattern, nameof(pattern));
|
||||
/// <inheritdoc cref="ICookiesRequestBuilder.WithCookie(string, string, bool, MatchBehaviour)"/>
|
||||
public IRequestBuilder WithCookie(string name, string pattern, bool ignoreCase = true, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
|
||||
{
|
||||
Guard.NotNull(name, nameof(name));
|
||||
Guard.NotNull(pattern, nameof(pattern));
|
||||
|
||||
_requestMatchers.Add(new RequestMessageCookieMatcher(matchBehaviour, name, pattern, ignoreCase));
|
||||
return this;
|
||||
}
|
||||
_requestMatchers.Add(new RequestMessageCookieMatcher(matchBehaviour, name, pattern, ignoreCase));
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="ICookiesRequestBuilder.WithCookie(string, string[], MatchBehaviour)"/>
|
||||
public IRequestBuilder WithCookie(string name, string[] patterns, MatchBehaviour matchBehaviour)
|
||||
{
|
||||
return WithCookie(name, patterns, true, matchBehaviour);
|
||||
}
|
||||
/// <inheritdoc cref="ICookiesRequestBuilder.WithCookie(string, string[], MatchBehaviour)"/>
|
||||
public IRequestBuilder WithCookie(string name, string[] patterns, MatchBehaviour matchBehaviour)
|
||||
{
|
||||
return WithCookie(name, patterns, true, matchBehaviour);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="ICookiesRequestBuilder.WithCookie(string, string[], bool, MatchBehaviour)"/>
|
||||
public IRequestBuilder WithCookie(string name, string[] patterns, bool ignoreCase = true, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
|
||||
{
|
||||
Guard.NotNull(name, nameof(name));
|
||||
Guard.NotNull(patterns, nameof(patterns));
|
||||
/// <inheritdoc cref="ICookiesRequestBuilder.WithCookie(string, string[], bool, MatchBehaviour)"/>
|
||||
public IRequestBuilder WithCookie(string name, string[] patterns, bool ignoreCase = true, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
|
||||
{
|
||||
Guard.NotNull(name, nameof(name));
|
||||
Guard.NotNull(patterns, nameof(patterns));
|
||||
|
||||
_requestMatchers.Add(new RequestMessageCookieMatcher(matchBehaviour, name, ignoreCase, patterns));
|
||||
return this;
|
||||
}
|
||||
_requestMatchers.Add(new RequestMessageCookieMatcher(matchBehaviour, name, ignoreCase, patterns));
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="ICookiesRequestBuilder.WithCookie(string, IStringMatcher[])"/>
|
||||
public IRequestBuilder WithCookie(string name, params IStringMatcher[] matchers)
|
||||
{
|
||||
Guard.NotNull(name, nameof(name));
|
||||
Guard.NotNullOrEmpty(matchers, nameof(matchers));
|
||||
/// <inheritdoc cref="ICookiesRequestBuilder.WithCookie(string, IStringMatcher[])"/>
|
||||
public IRequestBuilder WithCookie(string name, params IStringMatcher[] matchers)
|
||||
{
|
||||
Guard.NotNull(name, nameof(name));
|
||||
Guard.NotNullOrEmpty(matchers, nameof(matchers));
|
||||
|
||||
_requestMatchers.Add(new RequestMessageCookieMatcher(MatchBehaviour.AcceptOnMatch, name, false, matchers));
|
||||
return this;
|
||||
}
|
||||
_requestMatchers.Add(new RequestMessageCookieMatcher(MatchBehaviour.AcceptOnMatch, name, false, matchers));
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="ICookiesRequestBuilder.WithCookie(string, bool, IStringMatcher[])"/>
|
||||
public IRequestBuilder WithCookie(string name, bool ignoreCase, params IStringMatcher[] matchers)
|
||||
{
|
||||
Guard.NotNull(name, nameof(name));
|
||||
Guard.NotNullOrEmpty(matchers, nameof(matchers));
|
||||
/// <inheritdoc cref="ICookiesRequestBuilder.WithCookie(string, bool, IStringMatcher[])"/>
|
||||
public IRequestBuilder WithCookie(string name, bool ignoreCase, params IStringMatcher[] matchers)
|
||||
{
|
||||
Guard.NotNull(name, nameof(name));
|
||||
Guard.NotNullOrEmpty(matchers, nameof(matchers));
|
||||
|
||||
_requestMatchers.Add(new RequestMessageCookieMatcher(MatchBehaviour.AcceptOnMatch, name, ignoreCase, matchers));
|
||||
return this;
|
||||
}
|
||||
_requestMatchers.Add(new RequestMessageCookieMatcher(MatchBehaviour.AcceptOnMatch, name, ignoreCase, matchers));
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="ICookiesRequestBuilder.WithCookie(string, IStringMatcher[])"/>
|
||||
public IRequestBuilder WithCookie(string name, bool ignoreCase, MatchBehaviour matchBehaviour, params IStringMatcher[] matchers)
|
||||
{
|
||||
Guard.NotNull(name, nameof(name));
|
||||
Guard.NotNullOrEmpty(matchers, nameof(matchers));
|
||||
/// <inheritdoc cref="ICookiesRequestBuilder.WithCookie(string, IStringMatcher[])"/>
|
||||
public IRequestBuilder WithCookie(string name, bool ignoreCase, MatchBehaviour matchBehaviour, params IStringMatcher[] matchers)
|
||||
{
|
||||
Guard.NotNull(name, nameof(name));
|
||||
Guard.NotNullOrEmpty(matchers, nameof(matchers));
|
||||
|
||||
_requestMatchers.Add(new RequestMessageCookieMatcher(matchBehaviour, name, ignoreCase, matchers));
|
||||
return this;
|
||||
}
|
||||
_requestMatchers.Add(new RequestMessageCookieMatcher(matchBehaviour, name, ignoreCase, matchers));
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="ICookiesRequestBuilder.WithCookie(Func{IDictionary{string, string}, bool}[])"/>
|
||||
public IRequestBuilder WithCookie(params Func<IDictionary<string, string>, bool>[] funcs)
|
||||
{
|
||||
Guard.NotNullOrEmpty(funcs, nameof(funcs));
|
||||
/// <inheritdoc cref="ICookiesRequestBuilder.WithCookie(Func{IDictionary{string, string}, bool}[])"/>
|
||||
public IRequestBuilder WithCookie(params Func<IDictionary<string, string>, bool>[] funcs)
|
||||
{
|
||||
Guard.NotNullOrEmpty(funcs, nameof(funcs));
|
||||
|
||||
_requestMatchers.Add(new RequestMessageCookieMatcher(funcs));
|
||||
return this;
|
||||
}
|
||||
_requestMatchers.Add(new RequestMessageCookieMatcher(funcs));
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -7,86 +7,85 @@ using WireMock.Matchers.Request;
|
||||
using WireMock.Types;
|
||||
using Stef.Validation;
|
||||
|
||||
namespace WireMock.RequestBuilders
|
||||
namespace WireMock.RequestBuilders;
|
||||
|
||||
public partial class Request
|
||||
{
|
||||
public partial class Request
|
||||
/// <inheritdoc cref="IParamsRequestBuilder.WithParam(string, MatchBehaviour)"/>
|
||||
public IRequestBuilder WithParam(string key, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
|
||||
{
|
||||
/// <inheritdoc cref="IParamsRequestBuilder.WithParam(string, MatchBehaviour)"/>
|
||||
public IRequestBuilder WithParam(string key, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
|
||||
{
|
||||
return WithParam(key, false, matchBehaviour);
|
||||
}
|
||||
return WithParam(key, false, matchBehaviour);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IParamsRequestBuilder.WithParam(string, bool, MatchBehaviour)"/>
|
||||
public IRequestBuilder WithParam(string key, bool ignoreCase, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
|
||||
{
|
||||
Guard.NotNull(key);
|
||||
/// <inheritdoc cref="IParamsRequestBuilder.WithParam(string, bool, MatchBehaviour)"/>
|
||||
public IRequestBuilder WithParam(string key, bool ignoreCase, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
|
||||
{
|
||||
Guard.NotNull(key);
|
||||
|
||||
_requestMatchers.Add(new RequestMessageParamMatcher(matchBehaviour, key, ignoreCase));
|
||||
return this;
|
||||
}
|
||||
_requestMatchers.Add(new RequestMessageParamMatcher(matchBehaviour, key, ignoreCase));
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IParamsRequestBuilder.WithParam(string, string[])"/>
|
||||
public IRequestBuilder WithParam(string key, params string[] values)
|
||||
{
|
||||
return WithParam(key, MatchBehaviour.AcceptOnMatch, false, values);
|
||||
}
|
||||
/// <inheritdoc cref="IParamsRequestBuilder.WithParam(string, string[])"/>
|
||||
public IRequestBuilder WithParam(string key, params string[] values)
|
||||
{
|
||||
return WithParam(key, MatchBehaviour.AcceptOnMatch, false, values);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IParamsRequestBuilder.WithParam(string, bool, string[])"/>
|
||||
public IRequestBuilder WithParam(string key, bool ignoreCase, params string[] values)
|
||||
{
|
||||
return WithParam(key, MatchBehaviour.AcceptOnMatch, ignoreCase, values);
|
||||
}
|
||||
/// <inheritdoc cref="IParamsRequestBuilder.WithParam(string, bool, string[])"/>
|
||||
public IRequestBuilder WithParam(string key, bool ignoreCase, params string[] values)
|
||||
{
|
||||
return WithParam(key, MatchBehaviour.AcceptOnMatch, ignoreCase, values);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IParamsRequestBuilder.WithParam(string, IStringMatcher[])"/>
|
||||
public IRequestBuilder WithParam(string key, params IStringMatcher[] matchers)
|
||||
{
|
||||
return WithParam(key, MatchBehaviour.AcceptOnMatch, false, matchers);
|
||||
}
|
||||
/// <inheritdoc cref="IParamsRequestBuilder.WithParam(string, IStringMatcher[])"/>
|
||||
public IRequestBuilder WithParam(string key, params IStringMatcher[] matchers)
|
||||
{
|
||||
return WithParam(key, MatchBehaviour.AcceptOnMatch, false, matchers);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IParamsRequestBuilder.WithParam(string, bool, IStringMatcher[])"/>
|
||||
public IRequestBuilder WithParam(string key, bool ignoreCase, params IStringMatcher[] matchers)
|
||||
{
|
||||
return WithParam(key, MatchBehaviour.AcceptOnMatch, ignoreCase, matchers);
|
||||
}
|
||||
/// <inheritdoc cref="IParamsRequestBuilder.WithParam(string, bool, IStringMatcher[])"/>
|
||||
public IRequestBuilder WithParam(string key, bool ignoreCase, params IStringMatcher[] matchers)
|
||||
{
|
||||
return WithParam(key, MatchBehaviour.AcceptOnMatch, ignoreCase, matchers);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IParamsRequestBuilder.WithParam(string, MatchBehaviour, string[])"/>
|
||||
public IRequestBuilder WithParam(string key, MatchBehaviour matchBehaviour, params string[] values)
|
||||
{
|
||||
return WithParam(key, matchBehaviour, false, values);
|
||||
}
|
||||
/// <inheritdoc cref="IParamsRequestBuilder.WithParam(string, MatchBehaviour, string[])"/>
|
||||
public IRequestBuilder WithParam(string key, MatchBehaviour matchBehaviour, params string[] values)
|
||||
{
|
||||
return WithParam(key, matchBehaviour, false, values);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IParamsRequestBuilder.WithParam(string, MatchBehaviour, bool, string[])"/>
|
||||
public IRequestBuilder WithParam(string key, MatchBehaviour matchBehaviour, bool ignoreCase = false, params string[] values)
|
||||
{
|
||||
Guard.NotNull(key);
|
||||
/// <inheritdoc cref="IParamsRequestBuilder.WithParam(string, MatchBehaviour, bool, string[])"/>
|
||||
public IRequestBuilder WithParam(string key, MatchBehaviour matchBehaviour, bool ignoreCase = false, params string[] values)
|
||||
{
|
||||
Guard.NotNull(key);
|
||||
|
||||
_requestMatchers.Add(new RequestMessageParamMatcher(matchBehaviour, key, ignoreCase, values));
|
||||
return this;
|
||||
}
|
||||
_requestMatchers.Add(new RequestMessageParamMatcher(matchBehaviour, key, ignoreCase, values));
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IParamsRequestBuilder.WithParam(string, MatchBehaviour, IStringMatcher[])"/>
|
||||
public IRequestBuilder WithParam(string key, MatchBehaviour matchBehaviour, params IStringMatcher[] matchers)
|
||||
{
|
||||
return WithParam(key, matchBehaviour, false, matchers);
|
||||
}
|
||||
/// <inheritdoc cref="IParamsRequestBuilder.WithParam(string, MatchBehaviour, IStringMatcher[])"/>
|
||||
public IRequestBuilder WithParam(string key, MatchBehaviour matchBehaviour, params IStringMatcher[] matchers)
|
||||
{
|
||||
return WithParam(key, matchBehaviour, false, matchers);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IParamsRequestBuilder.WithParam(string, MatchBehaviour, bool, IStringMatcher[])"/>
|
||||
public IRequestBuilder WithParam(string key, MatchBehaviour matchBehaviour, bool ignoreCase, params IStringMatcher[] matchers)
|
||||
{
|
||||
Guard.NotNull(key);
|
||||
/// <inheritdoc cref="IParamsRequestBuilder.WithParam(string, MatchBehaviour, bool, IStringMatcher[])"/>
|
||||
public IRequestBuilder WithParam(string key, MatchBehaviour matchBehaviour, bool ignoreCase, params IStringMatcher[] matchers)
|
||||
{
|
||||
Guard.NotNull(key);
|
||||
|
||||
_requestMatchers.Add(new RequestMessageParamMatcher(matchBehaviour, key, ignoreCase, matchers));
|
||||
return this;
|
||||
}
|
||||
_requestMatchers.Add(new RequestMessageParamMatcher(matchBehaviour, key, ignoreCase, matchers));
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IParamsRequestBuilder.WithParam(Func{IDictionary{string, WireMockList{string}}, bool}[])"/>
|
||||
public IRequestBuilder WithParam(params Func<IDictionary<string, WireMockList<string>>, bool>[] funcs)
|
||||
{
|
||||
Guard.NotNullOrEmpty(funcs, nameof(funcs));
|
||||
/// <inheritdoc cref="IParamsRequestBuilder.WithParam(Func{IDictionary{string, WireMockList{string}}, bool}[])"/>
|
||||
public IRequestBuilder WithParam(params Func<IDictionary<string, WireMockList<string>>, bool>[] funcs)
|
||||
{
|
||||
Guard.NotNullOrEmpty(funcs, nameof(funcs));
|
||||
|
||||
_requestMatchers.Add(new RequestMessageParamMatcher(funcs));
|
||||
return this;
|
||||
}
|
||||
_requestMatchers.Add(new RequestMessageParamMatcher(funcs));
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -3,47 +3,46 @@ using Stef.Validation;
|
||||
using WireMock.Matchers;
|
||||
using WireMock.Matchers.Request;
|
||||
|
||||
namespace WireMock.RequestBuilders
|
||||
namespace WireMock.RequestBuilders;
|
||||
|
||||
public partial class Request
|
||||
{
|
||||
public partial class Request
|
||||
/// <inheritdoc />
|
||||
public IRequestBuilder WithUrl(params IStringMatcher[] matchers)
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public IRequestBuilder WithUrl(params IStringMatcher[] matchers)
|
||||
{
|
||||
return WithUrl(MatchOperator.Or, matchers);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IRequestBuilder WithUrl(MatchOperator matchOperator, params IStringMatcher[] matchers)
|
||||
{
|
||||
Guard.NotNullOrEmpty(matchers);
|
||||
|
||||
_requestMatchers.Add(new RequestMessageUrlMatcher(MatchBehaviour.AcceptOnMatch, matchOperator, matchers));
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IRequestBuilder WithUrl(params string[] urls)
|
||||
{
|
||||
return WithUrl(MatchOperator.Or, urls);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IRequestBuilder WithUrl(MatchOperator matchOperator, params string[] urls)
|
||||
{
|
||||
Guard.NotNullOrEmpty(urls);
|
||||
|
||||
_requestMatchers.Add(new RequestMessageUrlMatcher(MatchBehaviour.AcceptOnMatch, matchOperator, urls));
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IUrlAndPathRequestBuilder.WithUrl(Func{string, bool}[])"/>
|
||||
public IRequestBuilder WithUrl(params Func<string, bool>[] funcs)
|
||||
{
|
||||
Guard.NotNullOrEmpty(funcs);
|
||||
|
||||
_requestMatchers.Add(new RequestMessageUrlMatcher(funcs));
|
||||
return this;
|
||||
}
|
||||
return WithUrl(MatchOperator.Or, matchers);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IRequestBuilder WithUrl(MatchOperator matchOperator, params IStringMatcher[] matchers)
|
||||
{
|
||||
Guard.NotNullOrEmpty(matchers);
|
||||
|
||||
_requestMatchers.Add(new RequestMessageUrlMatcher(MatchBehaviour.AcceptOnMatch, matchOperator, matchers));
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IRequestBuilder WithUrl(params string[] urls)
|
||||
{
|
||||
return WithUrl(MatchOperator.Or, urls);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IRequestBuilder WithUrl(MatchOperator matchOperator, params string[] urls)
|
||||
{
|
||||
Guard.NotNullOrEmpty(urls);
|
||||
|
||||
_requestMatchers.Add(new RequestMessageUrlMatcher(MatchBehaviour.AcceptOnMatch, matchOperator, urls));
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IUrlAndPathRequestBuilder.WithUrl(Func{string, bool}[])"/>
|
||||
public IRequestBuilder WithUrl(params Func<string, bool>[] funcs)
|
||||
{
|
||||
Guard.NotNullOrEmpty(funcs);
|
||||
|
||||
_requestMatchers.Add(new RequestMessageUrlMatcher(funcs));
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -63,5 +63,4 @@ public partial class Request : RequestMessageCompositeMatcher, IRequestBuilder
|
||||
{
|
||||
return _requestMatchers.OfType<T>().FirstOrDefault(func);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
@@ -14,6 +15,7 @@ using WireMock.RequestBuilders;
|
||||
using WireMock.ResponseBuilders;
|
||||
using WireMock.Settings;
|
||||
using WireMock.Types;
|
||||
using WireMock.Util;
|
||||
|
||||
namespace WireMock.Serialization;
|
||||
|
||||
@@ -33,7 +35,7 @@ internal class MappingConverter
|
||||
settings ??= new MappingConverterSettings();
|
||||
|
||||
var request = (Request)mapping.RequestMatcher;
|
||||
var response = (Response) mapping.Provider;
|
||||
var response = (Response)mapping.Provider;
|
||||
|
||||
var clientIPMatcher = request.GetRequestMessageMatcher<RequestMessageClientIPMatcher>();
|
||||
var pathMatcher = request.GetRequestMessageMatcher<RequestMessagePathMatcher>();
|
||||
@@ -115,6 +117,11 @@ internal class MappingConverter
|
||||
// Guid
|
||||
sb.AppendLine($" .WithGuid(\"{mapping.Guid}\")");
|
||||
|
||||
if (mapping.Probability != null)
|
||||
{
|
||||
sb.AppendLine($" .WithProbability({mapping.Probability.Value.ToString(CultureInfoUtils.CultureInfoEnUS)})");
|
||||
}
|
||||
|
||||
// Response
|
||||
sb.AppendLine(" .RespondWith(Response.Create()");
|
||||
|
||||
@@ -183,6 +190,7 @@ internal class MappingConverter
|
||||
WhenStateIs = mapping.ExecutionConditionState,
|
||||
SetStateTo = mapping.NextState,
|
||||
Data = mapping.Data,
|
||||
Probability = mapping.Probability,
|
||||
Request = new RequestModel
|
||||
{
|
||||
Headers = headerMatchers.Any() ? headerMatchers.Select(hm => new HeaderModel
|
||||
|
||||
@@ -189,7 +189,8 @@ internal class ProxyMappingConverter
|
||||
webhooks: null,
|
||||
useWebhooksFireAndForget: null,
|
||||
timeSettings: null,
|
||||
data: mapping?.Data
|
||||
data: mapping?.Data,
|
||||
probability: null
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -175,5 +175,13 @@ public interface IRespondWithAProvider
|
||||
/// lookup data "1"
|
||||
/// </example>
|
||||
/// </summary>
|
||||
/// <returns>The <see cref="IRespondWithAProvider"/>.</returns>
|
||||
IRespondWithAProvider WithData(object data);
|
||||
|
||||
/// <summary>
|
||||
/// Define the probability when this request should be matched. Value is between 0 and 1.
|
||||
/// </summary>
|
||||
/// <param name="probability">The probability when this request should be matched. Value is between 0 and 1.</param>
|
||||
/// <returns>The <see cref="IRespondWithAProvider"/>.</returns>
|
||||
IRespondWithAProvider WithProbability(double probability);
|
||||
}
|
||||
@@ -18,6 +18,12 @@ namespace WireMock.Server;
|
||||
/// </summary>
|
||||
internal class RespondWithAProvider : IRespondWithAProvider
|
||||
{
|
||||
private readonly RegistrationCallback _registrationCallback;
|
||||
private readonly IRequestMatcher _requestMatcher;
|
||||
private readonly WireMockServerSettings _settings;
|
||||
private readonly IDateTimeUtils _dateTimeUtils;
|
||||
private readonly bool _saveToFile;
|
||||
|
||||
private int _priority;
|
||||
private string? _title;
|
||||
private string? _description;
|
||||
@@ -26,13 +32,8 @@ internal class RespondWithAProvider : IRespondWithAProvider
|
||||
private string? _nextState;
|
||||
private string? _scenario;
|
||||
private int _timesInSameState = 1;
|
||||
private readonly RegistrationCallback _registrationCallback;
|
||||
private readonly IRequestMatcher _requestMatcher;
|
||||
private readonly WireMockServerSettings _settings;
|
||||
private readonly IDateTimeUtils _dateTimeUtils;
|
||||
private readonly bool _saveToFile;
|
||||
|
||||
private bool? _useWebhookFireAndForget;
|
||||
private double? _probability;
|
||||
|
||||
public Guid Guid { get; private set; }
|
||||
|
||||
@@ -92,7 +93,8 @@ internal class RespondWithAProvider : IRespondWithAProvider
|
||||
Webhooks,
|
||||
_useWebhookFireAndForget,
|
||||
TimeSettings,
|
||||
Data);
|
||||
Data,
|
||||
_probability);
|
||||
|
||||
_registrationCallback(mapping, _saveToFile);
|
||||
}
|
||||
@@ -285,6 +287,13 @@ internal class RespondWithAProvider : IRespondWithAProvider
|
||||
return this;
|
||||
}
|
||||
|
||||
public IRespondWithAProvider WithProbability(double probability)
|
||||
{
|
||||
_probability = Guard.Condition(probability, p => p is >= 0 and <= 1.0);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
private static IWebhook InitWebhook(
|
||||
string url,
|
||||
string method,
|
||||
|
||||
@@ -113,6 +113,11 @@ public partial class WireMockServer
|
||||
respondProvider.WithWebhookFireAndForget(mappingModel.UseWebhooksFireAndForget.Value);
|
||||
}
|
||||
|
||||
if (mappingModel.Probability != null)
|
||||
{
|
||||
respondProvider.WithProbability(mappingModel.Probability.Value);
|
||||
}
|
||||
|
||||
var responseBuilder = InitResponseBuilder(mappingModel.Response);
|
||||
respondProvider.RespondWith(responseBuilder);
|
||||
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace WireMock.Services;
|
||||
|
||||
internal interface IRandomizerDoubleBetween0And1
|
||||
{
|
||||
double Generate();
|
||||
}
|
||||
14
src/WireMock.Net/Services/RandomizerDoubleBetween0And1.cs
Normal file
14
src/WireMock.Net/Services/RandomizerDoubleBetween0And1.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using RandomDataGenerator.FieldOptions;
|
||||
using RandomDataGenerator.Randomizers;
|
||||
|
||||
namespace WireMock.Services;
|
||||
|
||||
internal class RandomizerDoubleBetween0And1 : IRandomizerDoubleBetween0And1
|
||||
{
|
||||
private readonly IRandomizerNumber<double> _randomizerDoubleBetween0And1 = RandomizerFactory.GetRandomizer(new FieldOptionsDouble { Min = 0, Max = 1 });
|
||||
|
||||
public double Generate()
|
||||
{
|
||||
return _randomizerDoubleBetween0And1.Generate() ?? 0;
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,8 @@ namespace WireMock.Util;
|
||||
|
||||
internal static class CultureInfoUtils
|
||||
{
|
||||
public static readonly CultureInfo CultureInfoEnUS = new("en-US");
|
||||
|
||||
public static CultureInfo Parse(string? value)
|
||||
{
|
||||
if (value is null)
|
||||
|
||||
@@ -1,16 +1,11 @@
|
||||
namespace WireMock.Org.Abstractions
|
||||
namespace WireMock.Org.Abstractions;
|
||||
|
||||
/// <summary>
|
||||
/// The fault to apply (instead of a full, valid response).
|
||||
/// </summary>
|
||||
public static class MappingsResponseFaultConstants
|
||||
{
|
||||
/// <summary>
|
||||
/// The fault to apply (instead of a full, valid response).
|
||||
/// </summary>
|
||||
public static class MappingsResponseFaultConstants
|
||||
{
|
||||
public const string CONNECTIONRESETBYPEER = "CONNECTION_RESET_BY_PEER";
|
||||
public const string EMPTYRESPONSE = "EMPTY_RESPONSE";
|
||||
|
||||
public const string EMPTYRESPONSE = "EMPTY_RESPONSE";
|
||||
|
||||
public const string MALFORMEDRESPONSECHUNK = "MALFORMED_RESPONSE_CHUNK";
|
||||
|
||||
public const string RANDOMDATATHENCLOSE = "RANDOM_DATA_THEN_CLOSE";
|
||||
}
|
||||
}
|
||||
public const string MALFORMEDRESPONSECHUNK = "MALFORMED_RESPONSE_CHUNK";
|
||||
}
|
||||
@@ -6,6 +6,7 @@ using WireMock.Logging;
|
||||
using WireMock.Matchers.Request;
|
||||
using WireMock.Models;
|
||||
using WireMock.Owin;
|
||||
using WireMock.Services;
|
||||
using WireMock.Util;
|
||||
using Xunit;
|
||||
|
||||
@@ -14,6 +15,8 @@ namespace WireMock.Net.Tests.Owin;
|
||||
public class MappingMatcherTests
|
||||
{
|
||||
private readonly Mock<IWireMockMiddlewareOptions> _optionsMock;
|
||||
private readonly Mock<IRandomizerDoubleBetween0And1> _randomizerDoubleBetween0And1Mock;
|
||||
|
||||
private readonly MappingMatcher _sut;
|
||||
|
||||
public MappingMatcherTests()
|
||||
@@ -29,7 +32,10 @@ public class MappingMatcherTests
|
||||
loggerMock.Setup(l => l.Error(It.IsAny<string>()));
|
||||
_optionsMock.Setup(o => o.Logger).Returns(loggerMock.Object);
|
||||
|
||||
_sut = new MappingMatcher(_optionsMock.Object);
|
||||
_randomizerDoubleBetween0And1Mock = new Mock<IRandomizerDoubleBetween0And1>();
|
||||
_randomizerDoubleBetween0And1Mock.Setup(r => r.Generate()).Returns(0.0);
|
||||
|
||||
_sut = new MappingMatcher(_optionsMock.Object, _randomizerDoubleBetween0And1Mock.Object);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -76,8 +82,8 @@ public class MappingMatcherTests
|
||||
var guid2 = Guid.Parse("00000000-0000-0000-0000-000000000002");
|
||||
var mappings = InitMappings
|
||||
(
|
||||
(guid1, new[] { 0.1 }),
|
||||
(guid2, new[] { 1.0 })
|
||||
(guid1, new[] { 0.1 }, null),
|
||||
(guid2, new[] { 1.0 }, null)
|
||||
);
|
||||
_optionsMock.Setup(o => o.Mappings).Returns(mappings);
|
||||
|
||||
@@ -104,8 +110,8 @@ public class MappingMatcherTests
|
||||
var guid2 = Guid.Parse("00000000-0000-0000-0000-000000000002");
|
||||
var mappings = InitMappings
|
||||
(
|
||||
(guid1, new[] { 0.1 }),
|
||||
(guid2, new[] { 0.9 })
|
||||
(guid1, new[] { 0.1 }, null),
|
||||
(guid2, new[] { 0.9 }, null)
|
||||
);
|
||||
_optionsMock.Setup(o => o.Mappings).Returns(mappings);
|
||||
|
||||
@@ -131,8 +137,8 @@ public class MappingMatcherTests
|
||||
|
||||
_optionsMock.SetupGet(o => o.AllowPartialMapping).Returns(true);
|
||||
var mappings = InitMappings(
|
||||
(guid1, new[] { 0.1 }),
|
||||
(guid2, new[] { 0.9 })
|
||||
(guid1, new[] { 0.1 }, null),
|
||||
(guid2, new[] { 0.9 }, null)
|
||||
);
|
||||
_optionsMock.Setup(o => o.Mappings).Returns(mappings);
|
||||
|
||||
@@ -158,8 +164,8 @@ public class MappingMatcherTests
|
||||
var guid1 = Guid.Parse("00000000-0000-0000-0000-000000000001");
|
||||
var guid2 = Guid.Parse("00000000-0000-0000-0000-000000000002");
|
||||
var mappings = InitMappings(
|
||||
(guid1, new[] { 1.0 }),
|
||||
(guid2, new[] { 1.0, 1.0 })
|
||||
(guid1, new[] { 1.0 }, null),
|
||||
(guid2, new[] { 1.0, 1.0 }, null)
|
||||
);
|
||||
_optionsMock.Setup(o => o.Mappings).Returns(mappings);
|
||||
|
||||
@@ -178,7 +184,31 @@ public class MappingMatcherTests
|
||||
result.Partial.RequestMatchResult.AverageTotalScore.Should().Be(1.0);
|
||||
}
|
||||
|
||||
private static ConcurrentDictionary<Guid, IMapping> InitMappings(params (Guid guid, double[] scores)[] matches)
|
||||
[Fact]
|
||||
public void MappingMatcher_FindBestMatch_WhenProbabilityFailsFirst_ShouldReturnSecondMatch()
|
||||
{
|
||||
// Assign
|
||||
var guid1 = Guid.Parse("00000000-0000-0000-0000-000000000001");
|
||||
var guid2 = Guid.Parse("00000000-0000-0000-0000-000000000002");
|
||||
var mappings = InitMappings
|
||||
(
|
||||
(guid1, new[] { 1.0 }, 1.0),
|
||||
(guid2, new[] { 1.0 }, null)
|
||||
);
|
||||
_optionsMock.Setup(o => o.Mappings).Returns(mappings);
|
||||
|
||||
var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "GET", "::1");
|
||||
|
||||
// Act
|
||||
var result = _sut.FindBestMatch(request);
|
||||
|
||||
// Assert
|
||||
result.Match.Should().NotBeNull();
|
||||
result.Match!.Mapping.Guid.Should().Be(guid2);
|
||||
result.Match.RequestMatchResult.AverageTotalScore.Should().Be(1.0);
|
||||
}
|
||||
|
||||
private static ConcurrentDictionary<Guid, IMapping> InitMappings(params (Guid guid, double[] scores, double? probability)[] matches)
|
||||
{
|
||||
var mappings = new ConcurrentDictionary<Guid, IMapping>();
|
||||
|
||||
@@ -193,6 +223,8 @@ public class MappingMatcherTests
|
||||
requestMatchResult.AddScore(typeof(object), score);
|
||||
}
|
||||
|
||||
mappingMock.SetupGet(m => m.Probability).Returns(match.probability);
|
||||
|
||||
mappingMock.Setup(m => m.GetRequestMatchResult(It.IsAny<RequestMessage>(), It.IsAny<string>())).Returns(requestMatchResult);
|
||||
|
||||
mappings.TryAdd(match.guid, mappingMock.Object);
|
||||
|
||||
@@ -177,7 +177,7 @@ public class WireMockMiddlewareTests
|
||||
_mappingMock.SetupGet(m => m.Provider).Returns(responseBuilder);
|
||||
_mappingMock.SetupGet(m => m.Settings).Returns(settings);
|
||||
|
||||
var newMappingFromProxy = new Mapping(Guid.NewGuid(), _updatedAt, string.Empty, string.Empty, null, settings, Request.Create(), Response.Create(), 0, null, null, null, null, null, false, null, null);
|
||||
var newMappingFromProxy = new Mapping(Guid.NewGuid(), _updatedAt, string.Empty, string.Empty, null, settings, Request.Create(), Response.Create(), 0, null, null, null, null, null, false, null, null, null);
|
||||
_mappingMock.Setup(m => m.ProvideResponseAsync(It.IsAny<RequestMessage>())).ReturnsAsync((new ResponseMessage(), newMappingFromProxy));
|
||||
|
||||
var requestBuilder = Request.Create().UsingAnyMethod();
|
||||
@@ -231,7 +231,7 @@ public class WireMockMiddlewareTests
|
||||
_mappingMock.SetupGet(m => m.Provider).Returns(responseBuilder);
|
||||
_mappingMock.SetupGet(m => m.Settings).Returns(settings);
|
||||
|
||||
var newMappingFromProxy = new Mapping(Guid.NewGuid(), _updatedAt, "my-title", "my-description", null, settings, Request.Create(), Response.Create(), 0, null, null, null, null, null, false, null, data: null);
|
||||
var newMappingFromProxy = new Mapping(Guid.NewGuid(), _updatedAt, "my-title", "my-description", null, settings, Request.Create(), Response.Create(), 0, null, null, null, null, null, false, null, data: null, probability: null);
|
||||
_mappingMock.Setup(m => m.ProvideResponseAsync(It.IsAny<RequestMessage>())).ReturnsAsync((new ResponseMessage(), newMappingFromProxy));
|
||||
|
||||
var requestBuilder = Request.Create().UsingAnyMethod();
|
||||
|
||||
@@ -136,7 +136,8 @@ public partial class MappingConverterTests
|
||||
null,
|
||||
false,
|
||||
null,
|
||||
data: null
|
||||
data: null,
|
||||
probability: 0.3
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
.WithBody("b")
|
||||
)
|
||||
.WithGuid("8e7b9ab7-e18e-4502-8bc9-11e6679811cc")
|
||||
.WithProbability(0.3)
|
||||
.RespondWith(Response.Create()
|
||||
.WithHeader("Keep-Alive)", "test")
|
||||
.WithBody("bbb")
|
||||
|
||||
@@ -10,6 +10,7 @@ builder
|
||||
.WithBody("b")
|
||||
)
|
||||
.WithGuid("8e7b9ab7-e18e-4502-8bc9-11e6679811cc")
|
||||
.WithProbability(0.3)
|
||||
.RespondWith(Response.Create()
|
||||
.WithHeader("Keep-Alive)", "test")
|
||||
.WithBody("bbb")
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
.WithBody("b")
|
||||
)
|
||||
.WithGuid("8e7b9ab7-e18e-4502-8bc9-11e6679811cc")
|
||||
.WithProbability(0.3)
|
||||
.RespondWith(Response.Create()
|
||||
.WithHeader("Keep-Alive)", "test")
|
||||
.WithBody("bbb")
|
||||
|
||||
@@ -10,6 +10,7 @@ server
|
||||
.WithBody("b")
|
||||
)
|
||||
.WithGuid("8e7b9ab7-e18e-4502-8bc9-11e6679811cc")
|
||||
.WithProbability(0.3)
|
||||
.RespondWith(Response.Create()
|
||||
.WithHeader("Keep-Alive)", "test")
|
||||
.WithBody("bbb")
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
Guid: Guid_1,
|
||||
UpdatedAt: DateTime_1,
|
||||
Title: ,
|
||||
Description: ,
|
||||
Priority: 42,
|
||||
Request: {},
|
||||
Response: {},
|
||||
UseWebhooksFireAndForget: false,
|
||||
Probability: 0.4
|
||||
}
|
||||
@@ -57,7 +57,7 @@ public partial class MappingConverterTests
|
||||
}
|
||||
}
|
||||
};
|
||||
var mapping = new Mapping(_guid, _updatedAt, string.Empty, string.Empty, null, _settings, request, response, 0, null, null, null, null, webhooks, false, null, data: null);
|
||||
var mapping = new Mapping(_guid, _updatedAt, string.Empty, string.Empty, null, _settings, request, response, 0, null, null, null, null, webhooks, false, null, data: null, probability: null);
|
||||
|
||||
// Act
|
||||
var model = _sut.ToMappingModel(mapping);
|
||||
@@ -130,7 +130,7 @@ public partial class MappingConverterTests
|
||||
}
|
||||
}
|
||||
};
|
||||
var mapping = new Mapping(_guid, _updatedAt, string.Empty, string.Empty, null, _settings, request, response, 0, null, null, null, null, webhooks, true, null, data: null);
|
||||
var mapping = new Mapping(_guid, _updatedAt, string.Empty, string.Empty, null, _settings, request, response, 0, null, null, null, null, webhooks, true, null, data: null, probability: null);
|
||||
|
||||
// Act
|
||||
var model = _sut.ToMappingModel(mapping);
|
||||
@@ -168,7 +168,7 @@ public partial class MappingConverterTests
|
||||
var description = "my-description";
|
||||
var request = Request.Create();
|
||||
var response = Response.Create();
|
||||
var mapping = new Mapping(_guid, _updatedAt, title, description, null, _settings, request, response, 0, null, null, null, null, null, false, null, data: null);
|
||||
var mapping = new Mapping(_guid, _updatedAt, title, description, null, _settings, request, response, 0, null, null, null, null, null, false, null, data: null, probability: null);
|
||||
|
||||
// Act
|
||||
var model = _sut.ToMappingModel(mapping);
|
||||
@@ -188,7 +188,7 @@ public partial class MappingConverterTests
|
||||
// Assign
|
||||
var request = Request.Create();
|
||||
var response = Response.Create().WithBodyAsJson(new { x = "x" }).WithTransformer();
|
||||
var mapping = new Mapping(_guid, _updatedAt, string.Empty, string.Empty, null, _settings, request, response, 42, null, null, null, null, null, false, null, data: null);
|
||||
var mapping = new Mapping(_guid, _updatedAt, string.Empty, string.Empty, null, _settings, request, response, 42, null, null, null, null, null, false, null, data: null, probability: null);
|
||||
|
||||
// Act
|
||||
var model = _sut.ToMappingModel(mapping);
|
||||
@@ -217,7 +217,7 @@ public partial class MappingConverterTests
|
||||
End = end,
|
||||
TTL = ttl
|
||||
};
|
||||
var mapping = new Mapping(_guid, _updatedAt, string.Empty, string.Empty, null, _settings, request, response, 42, null, null, null, null, null, false, timeSettings, data: null);
|
||||
var mapping = new Mapping(_guid, _updatedAt, string.Empty, string.Empty, null, _settings, request, response, 42, null, null, null, null, null, false, timeSettings, data: null, probability: null);
|
||||
|
||||
// Act
|
||||
var model = _sut.ToMappingModel(mapping);
|
||||
@@ -248,7 +248,7 @@ public partial class MappingConverterTests
|
||||
{
|
||||
var request = Request.Create();
|
||||
var response = Response.Create().WithDelay(test.Delay);
|
||||
var mapping = new Mapping(Guid.NewGuid(), _updatedAt, string.Empty, string.Empty, string.Empty, _settings, request, response, 42, null, null, null, null, null, false, null, data: null);
|
||||
var mapping = new Mapping(Guid.NewGuid(), _updatedAt, string.Empty, string.Empty, string.Empty, _settings, request, response, 42, null, null, null, null, null, false, null, data: null, probability: null);
|
||||
|
||||
// Act
|
||||
var model = _sut.ToMappingModel(mapping);
|
||||
@@ -266,7 +266,7 @@ public partial class MappingConverterTests
|
||||
var delay = 1000;
|
||||
var request = Request.Create();
|
||||
var response = Response.Create().WithDelay(delay);
|
||||
var mapping = new Mapping(_guid, _updatedAt, string.Empty, string.Empty, null, _settings, request, response, 42, null, null, null, null, null, false, null, data: null);
|
||||
var mapping = new Mapping(_guid, _updatedAt, string.Empty, string.Empty, null, _settings, request, response, 42, null, null, null, null, null, false, null, data: null, probability: null);
|
||||
|
||||
// Act
|
||||
var model = _sut.ToMappingModel(mapping);
|
||||
@@ -286,7 +286,7 @@ public partial class MappingConverterTests
|
||||
int minimumDelay = 1000;
|
||||
var request = Request.Create();
|
||||
var response = Response.Create().WithRandomDelay(minimumDelay);
|
||||
var mapping = new Mapping(_guid, _updatedAt, string.Empty, string.Empty, null, _settings, request, response, 42, null, null, null, null, null, false, null, data: null);
|
||||
var mapping = new Mapping(_guid, _updatedAt, string.Empty, string.Empty, null, _settings, request, response, 42, null, null, null, null, null, false, null, data: null, probability: null);
|
||||
|
||||
// Act
|
||||
var model = _sut.ToMappingModel(mapping);
|
||||
@@ -309,7 +309,7 @@ public partial class MappingConverterTests
|
||||
int maximumDelay = 2000;
|
||||
var request = Request.Create();
|
||||
var response = Response.Create().WithRandomDelay(minimumDelay, maximumDelay);
|
||||
var mapping = new Mapping(_guid, _updatedAt, string.Empty, string.Empty, null, _settings, request, response, 42, null, null, null, null, null, false, null, data: null);
|
||||
var mapping = new Mapping(_guid, _updatedAt, string.Empty, string.Empty, null, _settings, request, response, 42, null, null, null, null, null, false, null, data: null, probability: null);
|
||||
|
||||
// Act
|
||||
var model = _sut.ToMappingModel(mapping);
|
||||
@@ -323,5 +323,25 @@ public partial class MappingConverterTests
|
||||
// Verify
|
||||
return Verifier.Verify(model);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public Task ToMappingModel_WithProbability_ReturnsCorrectModel()
|
||||
{
|
||||
// Assign
|
||||
double probability = 0.4;
|
||||
var request = Request.Create();
|
||||
var response = Response.Create();
|
||||
var mapping = new Mapping(_guid, _updatedAt, string.Empty, string.Empty, null, _settings, request, response, 42, null, null, null, null, null, false, null, data: null, probability: probability);
|
||||
|
||||
// Act
|
||||
var model = _sut.ToMappingModel(mapping);
|
||||
|
||||
// Assert
|
||||
model.Should().NotBeNull();
|
||||
model.Probability.Should().Be(0.4);
|
||||
|
||||
// Verify
|
||||
return Verifier.Verify(model);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,37 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Threading.Tasks;
|
||||
using WireMock.RequestBuilders;
|
||||
using WireMock.ResponseBuilders;
|
||||
using WireMock.Server;
|
||||
using Xunit;
|
||||
|
||||
namespace WireMock.Net.Tests;
|
||||
|
||||
public partial class WireMockServerTests
|
||||
{
|
||||
[Fact]
|
||||
public async Task WireMockServer_WithProbability()
|
||||
{
|
||||
// Arrange
|
||||
var server = WireMockServer.Start();
|
||||
server
|
||||
.Given(Request.Create().UsingGet().WithPath("/foo"))
|
||||
.WithProbability(0.5)
|
||||
.RespondWith(Response.Create().WithStatusCode(200));
|
||||
|
||||
server
|
||||
.Given(Request.Create().UsingGet().WithPath("/foo"))
|
||||
.RespondWith(Response.Create().WithStatusCode(500));
|
||||
|
||||
// Act
|
||||
var requestUri = new Uri($"http://localhost:{server.Port}/foo");
|
||||
var response = await server.CreateClient().GetAsync(requestUri).ConfigureAwait(false);
|
||||
|
||||
// Assert
|
||||
Assert.True(new[] { HttpStatusCode.OK, HttpStatusCode.InternalServerError }.Contains(response.StatusCode));
|
||||
|
||||
server.Stop();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user