diff --git a/src/WireMock.Net.Abstractions/Admin/Mappings/FaultModel.cs b/src/WireMock.Net.Abstractions/Admin/Mappings/FaultModel.cs
index a55728fe..622aeecc 100644
--- a/src/WireMock.Net.Abstractions/Admin/Mappings/FaultModel.cs
+++ b/src/WireMock.Net.Abstractions/Admin/Mappings/FaultModel.cs
@@ -1,19 +1,18 @@
-namespace WireMock.Admin.Mappings
+namespace WireMock.Admin.Mappings;
+
+///
+/// Fault Model
+///
+[FluentBuilder.AutoGenerateBuilder]
+public class FaultModel
{
///
- /// Fault Model
+ /// Gets or sets the fault. Can be null, "", NONE, EMPTY_RESPONSE or MALFORMED_RESPONSE_CHUNK.
///
- [FluentBuilder.AutoGenerateBuilder]
- public class FaultModel
- {
- ///
- /// Gets or sets the fault. Can be null, "", NONE, EMPTY_RESPONSE, MALFORMED_RESPONSE_CHUNK or RANDOM_DATA_THEN_CLOSE.
- ///
- public string Type { get; set; }
+ public string? Type { get; set; }
- ///
- /// Gets or sets the fault percentage.
- ///
- public double? Percentage { get; set; }
- }
+ ///
+ /// Gets or sets the fault percentage.
+ ///
+ public double? Percentage { get; set; }
}
\ No newline at end of file
diff --git a/src/WireMock.Net.Abstractions/Admin/Mappings/MappingModel.cs b/src/WireMock.Net.Abstractions/Admin/Mappings/MappingModel.cs
index d7932f4f..9f6061a2 100644
--- a/src/WireMock.Net.Abstractions/Admin/Mappings/MappingModel.cs
+++ b/src/WireMock.Net.Abstractions/Admin/Mappings/MappingModel.cs
@@ -1,5 +1,4 @@
using System;
-using System.Collections.Generic;
using WireMock.Models;
namespace WireMock.Admin.Mappings;
@@ -94,4 +93,9 @@ public class MappingModel
///
///
public object? Data { get; set; }
+
+ ///
+ /// The probability when this request should be matched. Value is between 0 and 1. [Optional]
+ ///
+ public double? Probability { get; set; }
}
\ No newline at end of file
diff --git a/src/WireMock.Net.Abstractions/ResponseBuilders/FaultType.cs b/src/WireMock.Net.Abstractions/ResponseBuilders/FaultType.cs
index 5c922868..d65951a7 100644
--- a/src/WireMock.Net.Abstractions/ResponseBuilders/FaultType.cs
+++ b/src/WireMock.Net.Abstractions/ResponseBuilders/FaultType.cs
@@ -1,23 +1,23 @@
-namespace WireMock.ResponseBuilders
+// ReSharper disable InconsistentNaming
+namespace WireMock.ResponseBuilders;
+
+///
+/// The FaultType enumeration
+///
+public enum FaultType
{
///
- /// The FaultType enumeration
+ /// No Fault
///
- public enum FaultType
- {
- ///
- /// No Fault
- ///
- NONE,
+ NONE,
- ///
- /// Return a completely empty response.
- ///
- EMPTY_RESPONSE,
+ ///
+ /// Return a completely empty response.
+ ///
+ EMPTY_RESPONSE,
- ///
- /// Send a defined status header, then garbage, then close the connection.
- ///
- MALFORMED_RESPONSE_CHUNK
- }
+ ///
+ /// Send a defined status header, then garbage, then close the connection.
+ ///
+ MALFORMED_RESPONSE_CHUNK
}
\ No newline at end of file
diff --git a/src/WireMock.Net/IMapping.cs b/src/WireMock.Net/IMapping.cs
index b53caa0a..20b3e947 100644
--- a/src/WireMock.Net/IMapping.cs
+++ b/src/WireMock.Net/IMapping.cs
@@ -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
///
object? Data { get; }
+ ///
+ /// The probability when this request should be matched. Value is between 0 and 1. [Optional]
+ ///
+ double? Probability { get; }
+
///
/// ProvideResponseAsync
///
diff --git a/src/WireMock.Net/Json/DynamicPropertyWithValue.cs b/src/WireMock.Net/Json/DynamicPropertyWithValue.cs
index 55219734..9cf2bd69 100644
--- a/src/WireMock.Net/Json/DynamicPropertyWithValue.cs
+++ b/src/WireMock.Net/Json/DynamicPropertyWithValue.cs
@@ -4,7 +4,7 @@ using System.Linq.Dynamic.Core;
namespace WireMock.Json;
-public class DynamicPropertyWithValue : DynamicProperty
+internal class DynamicPropertyWithValue : DynamicProperty
{
public object? Value { get; }
diff --git a/src/WireMock.Net/Mapping.cs b/src/WireMock.Net/Mapping.cs
index 6323fbe2..b678780a 100644
--- a/src/WireMock.Net/Mapping.cs
+++ b/src/WireMock.Net/Mapping.cs
@@ -75,6 +75,9 @@ public class Mapping : IMapping
///
public object? Data { get; }
+ ///
+ public double? Probability { get; }
+
///
/// Initializes a new instance of the class.
///
@@ -95,6 +98,7 @@ public class Mapping : IMapping
/// Use Fire and Forget for the defined webhook(s). [Optional]
/// The TimeSettings. [Optional]
/// The data object. [Optional]
+ /// Define the probability when this request should be matched. [Optional]
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;
}
///
diff --git a/src/WireMock.Net/MappingBuilder.cs b/src/WireMock.Net/MappingBuilder.cs
index 66ad1d4b..da6f479f 100644
--- a/src/WireMock.Net/MappingBuilder.cs
+++ b/src/WireMock.Net/MappingBuilder.cs
@@ -69,12 +69,7 @@ public class MappingBuilder : IMappingBuilder
///
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();
}
///
@@ -86,7 +81,7 @@ public class MappingBuilder : IMappingBuilder
///
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
///
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)
diff --git a/src/WireMock.Net/Matchers/Request/RequestMessageCompositeMatcher.cs b/src/WireMock.Net/Matchers/Request/RequestMessageCompositeMatcher.cs
index 1c8dfb20..0ecd738e 100644
--- a/src/WireMock.Net/Matchers/Request/RequestMessageCompositeMatcher.cs
+++ b/src/WireMock.Net/Matchers/Request/RequestMessageCompositeMatcher.cs
@@ -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
///
/// The request matchers.
/// The CompositeMatcherType type (Defaults to 'And')
- protected RequestMessageCompositeMatcher([NotNull] IEnumerable requestMatchers, CompositeMatcherType type = CompositeMatcherType.And)
+ protected RequestMessageCompositeMatcher(IEnumerable requestMatchers, CompositeMatcherType type = CompositeMatcherType.And)
{
- Guard.NotNull(requestMatchers, nameof(requestMatchers));
+ Guard.NotNull(requestMatchers);
_type = type;
RequestMatchers = requestMatchers;
diff --git a/src/WireMock.Net/Owin/AspNetCoreSelfHost.cs b/src/WireMock.Net/Owin/AspNetCoreSelfHost.cs
index 151c7d1b..60fefacd 100644
--- a/src/WireMock.Net/Owin/AspNetCoreSelfHost.cs
+++ b/src/WireMock.Net/Owin/AspNetCoreSelfHost.cs
@@ -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();
+ services.AddSingleton();
services.AddSingleton();
services.AddSingleton();
diff --git a/src/WireMock.Net/Owin/Mappers/OwinResponseMapper.cs b/src/WireMock.Net/Owin/Mappers/OwinResponseMapper.cs
index 3f0e1394..44857333 100644
--- a/src/WireMock.Net/Owin/Mappers/OwinResponseMapper.cs
+++ b/src/WireMock.Net/Owin/Mappers/OwinResponseMapper.cs
@@ -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.Value : GetNormalBody(responseMessage);
break;
case FaultType.MALFORMED_RESPONSE_CHUNK:
- bytes = GetNormalBody(responseMessage) ?? new byte[0];
+ bytes = GetNormalBody(responseMessage) ?? EmptyArray.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;
diff --git a/src/WireMock.Net/Owin/MappingMatcher.cs b/src/WireMock.Net/Owin/MappingMatcher.cs
index 6360e6a6..d979979c 100644
--- a/src/WireMock.Net/Owin/MappingMatcher.cs
+++ b/src/WireMock.Net/Owin/MappingMatcher.cs
@@ -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();
- 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
{
diff --git a/src/WireMock.Net/Owin/OwinSelfHost.cs b/src/WireMock.Net/Owin/OwinSelfHost.cs
index 58992ff1..7f4dbd3e 100644
--- a/src/WireMock.Net/Owin/OwinSelfHost.cs
+++ b/src/WireMock.Net/Owin/OwinSelfHost.cs
@@ -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 startup = app =>
{
diff --git a/src/WireMock.Net/RequestBuilders/IRequestBuilder.cs b/src/WireMock.Net/RequestBuilders/IRequestBuilder.cs
index 3662a38a..75303905 100644
--- a/src/WireMock.Net/RequestBuilders/IRequestBuilder.cs
+++ b/src/WireMock.Net/RequestBuilders/IRequestBuilder.cs
@@ -1,9 +1,8 @@
-namespace WireMock.RequestBuilders
+namespace WireMock.RequestBuilders;
+
+///
+/// IRequestBuilder
+///
+public interface IRequestBuilder : IClientIPRequestBuilder
{
- ///
- /// IRequestBuilder
- ///
- public interface IRequestBuilder : IClientIPRequestBuilder
- {
- }
}
\ No newline at end of file
diff --git a/src/WireMock.Net/RequestBuilders/Request.WithCookies.cs b/src/WireMock.Net/RequestBuilders/Request.WithCookies.cs
index 215b9887..c29b4595 100644
--- a/src/WireMock.Net/RequestBuilders/Request.WithCookies.cs
+++ b/src/WireMock.Net/RequestBuilders/Request.WithCookies.cs
@@ -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
+ ///
+ public IRequestBuilder WithCookie(string name, string pattern, MatchBehaviour matchBehaviour)
{
- ///
- public IRequestBuilder WithCookie(string name, string pattern, MatchBehaviour matchBehaviour)
- {
- return WithCookie(name, pattern, true, matchBehaviour);
- }
+ return WithCookie(name, pattern, true, 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));
+ ///
+ 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;
+ }
- ///
- public IRequestBuilder WithCookie(string name, string[] patterns, MatchBehaviour matchBehaviour)
- {
- return WithCookie(name, patterns, true, matchBehaviour);
- }
+ ///
+ public IRequestBuilder WithCookie(string name, string[] patterns, MatchBehaviour matchBehaviour)
+ {
+ return WithCookie(name, patterns, true, 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));
+ ///
+ 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;
+ }
- ///
- public IRequestBuilder WithCookie(string name, params IStringMatcher[] matchers)
- {
- Guard.NotNull(name, nameof(name));
- Guard.NotNullOrEmpty(matchers, nameof(matchers));
+ ///
+ 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;
+ }
- ///
- public IRequestBuilder WithCookie(string name, bool ignoreCase, params IStringMatcher[] matchers)
- {
- Guard.NotNull(name, nameof(name));
- Guard.NotNullOrEmpty(matchers, nameof(matchers));
+ ///
+ 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;
+ }
- ///
- public IRequestBuilder WithCookie(string name, bool ignoreCase, MatchBehaviour matchBehaviour, params IStringMatcher[] matchers)
- {
- Guard.NotNull(name, nameof(name));
- Guard.NotNullOrEmpty(matchers, nameof(matchers));
+ ///
+ 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;
+ }
- ///
- public IRequestBuilder WithCookie(params Func, bool>[] funcs)
- {
- Guard.NotNullOrEmpty(funcs, nameof(funcs));
+ ///
+ public IRequestBuilder WithCookie(params Func, bool>[] funcs)
+ {
+ Guard.NotNullOrEmpty(funcs, nameof(funcs));
- _requestMatchers.Add(new RequestMessageCookieMatcher(funcs));
- return this;
- }
+ _requestMatchers.Add(new RequestMessageCookieMatcher(funcs));
+ return this;
}
}
\ No newline at end of file
diff --git a/src/WireMock.Net/RequestBuilders/Request.WithParam.cs b/src/WireMock.Net/RequestBuilders/Request.WithParam.cs
index 06a925e6..5ce3034c 100644
--- a/src/WireMock.Net/RequestBuilders/Request.WithParam.cs
+++ b/src/WireMock.Net/RequestBuilders/Request.WithParam.cs
@@ -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
+ ///
+ public IRequestBuilder WithParam(string key, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
{
- ///
- public IRequestBuilder WithParam(string key, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
- {
- return WithParam(key, false, matchBehaviour);
- }
+ return WithParam(key, false, matchBehaviour);
+ }
- ///
- public IRequestBuilder WithParam(string key, bool ignoreCase, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
- {
- Guard.NotNull(key);
+ ///
+ 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;
+ }
- ///
- public IRequestBuilder WithParam(string key, params string[] values)
- {
- return WithParam(key, MatchBehaviour.AcceptOnMatch, false, values);
- }
+ ///
+ public IRequestBuilder WithParam(string key, params string[] values)
+ {
+ return WithParam(key, MatchBehaviour.AcceptOnMatch, false, values);
+ }
- ///
- public IRequestBuilder WithParam(string key, bool ignoreCase, params string[] values)
- {
- return WithParam(key, MatchBehaviour.AcceptOnMatch, ignoreCase, values);
- }
+ ///
+ public IRequestBuilder WithParam(string key, bool ignoreCase, params string[] values)
+ {
+ return WithParam(key, MatchBehaviour.AcceptOnMatch, ignoreCase, values);
+ }
- ///
- public IRequestBuilder WithParam(string key, params IStringMatcher[] matchers)
- {
- return WithParam(key, MatchBehaviour.AcceptOnMatch, false, matchers);
- }
+ ///
+ public IRequestBuilder WithParam(string key, params IStringMatcher[] matchers)
+ {
+ return WithParam(key, MatchBehaviour.AcceptOnMatch, false, matchers);
+ }
- ///
- public IRequestBuilder WithParam(string key, bool ignoreCase, params IStringMatcher[] matchers)
- {
- return WithParam(key, MatchBehaviour.AcceptOnMatch, ignoreCase, matchers);
- }
+ ///
+ public IRequestBuilder WithParam(string key, bool ignoreCase, params IStringMatcher[] matchers)
+ {
+ return WithParam(key, MatchBehaviour.AcceptOnMatch, ignoreCase, matchers);
+ }
- ///
- public IRequestBuilder WithParam(string key, MatchBehaviour matchBehaviour, params string[] values)
- {
- return WithParam(key, matchBehaviour, false, values);
- }
+ ///
+ public IRequestBuilder WithParam(string key, MatchBehaviour matchBehaviour, params string[] values)
+ {
+ return WithParam(key, matchBehaviour, false, values);
+ }
- ///
- public IRequestBuilder WithParam(string key, MatchBehaviour matchBehaviour, bool ignoreCase = false, params string[] values)
- {
- Guard.NotNull(key);
+ ///
+ 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;
+ }
- ///
- public IRequestBuilder WithParam(string key, MatchBehaviour matchBehaviour, params IStringMatcher[] matchers)
- {
- return WithParam(key, matchBehaviour, false, matchers);
- }
+ ///
+ public IRequestBuilder WithParam(string key, MatchBehaviour matchBehaviour, params IStringMatcher[] matchers)
+ {
+ return WithParam(key, matchBehaviour, false, matchers);
+ }
- ///
- public IRequestBuilder WithParam(string key, MatchBehaviour matchBehaviour, bool ignoreCase, params IStringMatcher[] matchers)
- {
- Guard.NotNull(key);
+ ///
+ 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;
+ }
- ///
- public IRequestBuilder WithParam(params Func>, bool>[] funcs)
- {
- Guard.NotNullOrEmpty(funcs, nameof(funcs));
+ ///
+ public IRequestBuilder WithParam(params Func>, bool>[] funcs)
+ {
+ Guard.NotNullOrEmpty(funcs, nameof(funcs));
- _requestMatchers.Add(new RequestMessageParamMatcher(funcs));
- return this;
- }
+ _requestMatchers.Add(new RequestMessageParamMatcher(funcs));
+ return this;
}
}
\ No newline at end of file
diff --git a/src/WireMock.Net/RequestBuilders/Request.WithUrl.cs b/src/WireMock.Net/RequestBuilders/Request.WithUrl.cs
index 6954623d..7f811e93 100644
--- a/src/WireMock.Net/RequestBuilders/Request.WithUrl.cs
+++ b/src/WireMock.Net/RequestBuilders/Request.WithUrl.cs
@@ -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
+ ///
+ public IRequestBuilder WithUrl(params IStringMatcher[] matchers)
{
- ///
- public IRequestBuilder WithUrl(params IStringMatcher[] matchers)
- {
- return WithUrl(MatchOperator.Or, matchers);
- }
-
- ///
- public IRequestBuilder WithUrl(MatchOperator matchOperator, params IStringMatcher[] matchers)
- {
- Guard.NotNullOrEmpty(matchers);
-
- _requestMatchers.Add(new RequestMessageUrlMatcher(MatchBehaviour.AcceptOnMatch, matchOperator, matchers));
- return this;
- }
-
- ///
- public IRequestBuilder WithUrl(params string[] urls)
- {
- return WithUrl(MatchOperator.Or, urls);
- }
-
- ///
- public IRequestBuilder WithUrl(MatchOperator matchOperator, params string[] urls)
- {
- Guard.NotNullOrEmpty(urls);
-
- _requestMatchers.Add(new RequestMessageUrlMatcher(MatchBehaviour.AcceptOnMatch, matchOperator, urls));
- return this;
- }
-
- ///
- public IRequestBuilder WithUrl(params Func[] funcs)
- {
- Guard.NotNullOrEmpty(funcs);
-
- _requestMatchers.Add(new RequestMessageUrlMatcher(funcs));
- return this;
- }
+ return WithUrl(MatchOperator.Or, matchers);
}
-}
+
+ ///
+ public IRequestBuilder WithUrl(MatchOperator matchOperator, params IStringMatcher[] matchers)
+ {
+ Guard.NotNullOrEmpty(matchers);
+
+ _requestMatchers.Add(new RequestMessageUrlMatcher(MatchBehaviour.AcceptOnMatch, matchOperator, matchers));
+ return this;
+ }
+
+ ///
+ public IRequestBuilder WithUrl(params string[] urls)
+ {
+ return WithUrl(MatchOperator.Or, urls);
+ }
+
+ ///
+ public IRequestBuilder WithUrl(MatchOperator matchOperator, params string[] urls)
+ {
+ Guard.NotNullOrEmpty(urls);
+
+ _requestMatchers.Add(new RequestMessageUrlMatcher(MatchBehaviour.AcceptOnMatch, matchOperator, urls));
+ return this;
+ }
+
+ ///
+ public IRequestBuilder WithUrl(params Func[] funcs)
+ {
+ Guard.NotNullOrEmpty(funcs);
+
+ _requestMatchers.Add(new RequestMessageUrlMatcher(funcs));
+ return this;
+ }
+}
\ No newline at end of file
diff --git a/src/WireMock.Net/RequestBuilders/Request.cs b/src/WireMock.Net/RequestBuilders/Request.cs
index 189c4a20..10255d5b 100644
--- a/src/WireMock.Net/RequestBuilders/Request.cs
+++ b/src/WireMock.Net/RequestBuilders/Request.cs
@@ -63,5 +63,4 @@ public partial class Request : RequestMessageCompositeMatcher, IRequestBuilder
{
return _requestMatchers.OfType().FirstOrDefault(func);
}
-
}
\ No newline at end of file
diff --git a/src/WireMock.Net/Serialization/MappingConverter.cs b/src/WireMock.Net/Serialization/MappingConverter.cs
index cba301c4..cc510da4 100644
--- a/src/WireMock.Net/Serialization/MappingConverter.cs
+++ b/src/WireMock.Net/Serialization/MappingConverter.cs
@@ -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();
var pathMatcher = request.GetRequestMessageMatcher();
@@ -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
diff --git a/src/WireMock.Net/Serialization/ProxyMappingConverter.cs b/src/WireMock.Net/Serialization/ProxyMappingConverter.cs
index 483cf294..0c5b2e53 100644
--- a/src/WireMock.Net/Serialization/ProxyMappingConverter.cs
+++ b/src/WireMock.Net/Serialization/ProxyMappingConverter.cs
@@ -189,7 +189,8 @@ internal class ProxyMappingConverter
webhooks: null,
useWebhooksFireAndForget: null,
timeSettings: null,
- data: mapping?.Data
+ data: mapping?.Data,
+ probability: null
);
}
}
\ No newline at end of file
diff --git a/src/WireMock.Net/Server/IRespondWithAProvider.cs b/src/WireMock.Net/Server/IRespondWithAProvider.cs
index 2f81df7e..b62840b5 100644
--- a/src/WireMock.Net/Server/IRespondWithAProvider.cs
+++ b/src/WireMock.Net/Server/IRespondWithAProvider.cs
@@ -175,5 +175,13 @@ public interface IRespondWithAProvider
/// lookup data "1"
///
///
+ /// The .
IRespondWithAProvider WithData(object data);
+
+ ///
+ /// Define the probability when this request should be matched. Value is between 0 and 1.
+ ///
+ /// The probability when this request should be matched. Value is between 0 and 1.
+ /// The .
+ IRespondWithAProvider WithProbability(double probability);
}
\ No newline at end of file
diff --git a/src/WireMock.Net/Server/RespondWithAProvider.cs b/src/WireMock.Net/Server/RespondWithAProvider.cs
index dc658183..7b7740fa 100644
--- a/src/WireMock.Net/Server/RespondWithAProvider.cs
+++ b/src/WireMock.Net/Server/RespondWithAProvider.cs
@@ -18,6 +18,12 @@ namespace WireMock.Server;
///
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,
diff --git a/src/WireMock.Net/Server/WireMockServer.ConvertMapping.cs b/src/WireMock.Net/Server/WireMockServer.ConvertMapping.cs
index 3786d839..8b5e97e9 100644
--- a/src/WireMock.Net/Server/WireMockServer.ConvertMapping.cs
+++ b/src/WireMock.Net/Server/WireMockServer.ConvertMapping.cs
@@ -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);
diff --git a/src/WireMock.Net/Services/IRandomizerDoubleBetween0And1.cs b/src/WireMock.Net/Services/IRandomizerDoubleBetween0And1.cs
new file mode 100644
index 00000000..9bf0480d
--- /dev/null
+++ b/src/WireMock.Net/Services/IRandomizerDoubleBetween0And1.cs
@@ -0,0 +1,6 @@
+namespace WireMock.Services;
+
+internal interface IRandomizerDoubleBetween0And1
+{
+ double Generate();
+}
\ No newline at end of file
diff --git a/src/WireMock.Net/Services/RandomizerDoubleBetween0And1.cs b/src/WireMock.Net/Services/RandomizerDoubleBetween0And1.cs
new file mode 100644
index 00000000..84e658e4
--- /dev/null
+++ b/src/WireMock.Net/Services/RandomizerDoubleBetween0And1.cs
@@ -0,0 +1,14 @@
+using RandomDataGenerator.FieldOptions;
+using RandomDataGenerator.Randomizers;
+
+namespace WireMock.Services;
+
+internal class RandomizerDoubleBetween0And1 : IRandomizerDoubleBetween0And1
+{
+ private readonly IRandomizerNumber _randomizerDoubleBetween0And1 = RandomizerFactory.GetRandomizer(new FieldOptionsDouble { Min = 0, Max = 1 });
+
+ public double Generate()
+ {
+ return _randomizerDoubleBetween0And1.Generate() ?? 0;
+ }
+}
\ No newline at end of file
diff --git a/src/WireMock.Net/Util/CultureInfoExtensions.cs b/src/WireMock.Net/Util/CultureInfoExtensions.cs
index 086c153e..2469804e 100644
--- a/src/WireMock.Net/Util/CultureInfoExtensions.cs
+++ b/src/WireMock.Net/Util/CultureInfoExtensions.cs
@@ -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)
diff --git a/src/WireMock.Org.Abstractions/MappingsResponseFaultConstants.cs b/src/WireMock.Org.Abstractions/MappingsResponseFaultConstants.cs
index 50bc8435..60d75fed 100644
--- a/src/WireMock.Org.Abstractions/MappingsResponseFaultConstants.cs
+++ b/src/WireMock.Org.Abstractions/MappingsResponseFaultConstants.cs
@@ -1,16 +1,11 @@
-namespace WireMock.Org.Abstractions
+namespace WireMock.Org.Abstractions;
+
+///
+/// The fault to apply (instead of a full, valid response).
+///
+public static class MappingsResponseFaultConstants
{
- ///
- /// The fault to apply (instead of a full, valid response).
- ///
- 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";
+}
\ No newline at end of file
diff --git a/test/WireMock.Net.Tests/Owin/MappingMatcherTests.cs b/test/WireMock.Net.Tests/Owin/MappingMatcherTests.cs
index 3ed1ba9b..b86aced4 100644
--- a/test/WireMock.Net.Tests/Owin/MappingMatcherTests.cs
+++ b/test/WireMock.Net.Tests/Owin/MappingMatcherTests.cs
@@ -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 _optionsMock;
+ private readonly Mock _randomizerDoubleBetween0And1Mock;
+
private readonly MappingMatcher _sut;
public MappingMatcherTests()
@@ -29,7 +32,10 @@ public class MappingMatcherTests
loggerMock.Setup(l => l.Error(It.IsAny()));
_optionsMock.Setup(o => o.Logger).Returns(loggerMock.Object);
- _sut = new MappingMatcher(_optionsMock.Object);
+ _randomizerDoubleBetween0And1Mock = new Mock();
+ _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 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 InitMappings(params (Guid guid, double[] scores, double? probability)[] matches)
{
var mappings = new ConcurrentDictionary();
@@ -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(), It.IsAny())).Returns(requestMatchResult);
mappings.TryAdd(match.guid, mappingMock.Object);
diff --git a/test/WireMock.Net.Tests/Owin/WireMockMiddlewareTests.cs b/test/WireMock.Net.Tests/Owin/WireMockMiddlewareTests.cs
index 4e253fc8..d42e1eaa 100644
--- a/test/WireMock.Net.Tests/Owin/WireMockMiddlewareTests.cs
+++ b/test/WireMock.Net.Tests/Owin/WireMockMiddlewareTests.cs
@@ -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())).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())).ReturnsAsync((new ResponseMessage(), newMappingFromProxy));
var requestBuilder = Request.Create().UsingAnyMethod();
diff --git a/test/WireMock.Net.Tests/Serialization/MappingConverterTests.ToCSharpCode.cs b/test/WireMock.Net.Tests/Serialization/MappingConverterTests.ToCSharpCode.cs
index 1e629313..c34a32d9 100644
--- a/test/WireMock.Net.Tests/Serialization/MappingConverterTests.ToCSharpCode.cs
+++ b/test/WireMock.Net.Tests/Serialization/MappingConverterTests.ToCSharpCode.cs
@@ -136,7 +136,8 @@ public partial class MappingConverterTests
null,
false,
null,
- data: null
+ data: null,
+ probability: 0.3
);
}
}
diff --git a/test/WireMock.Net.Tests/Serialization/MappingConverterTests.ToCSharpCode_With_Builder_And_AddStartIsFalse.verified.txt b/test/WireMock.Net.Tests/Serialization/MappingConverterTests.ToCSharpCode_With_Builder_And_AddStartIsFalse.verified.txt
index 19739c17..bd54bf3d 100644
--- a/test/WireMock.Net.Tests/Serialization/MappingConverterTests.ToCSharpCode_With_Builder_And_AddStartIsFalse.verified.txt
+++ b/test/WireMock.Net.Tests/Serialization/MappingConverterTests.ToCSharpCode_With_Builder_And_AddStartIsFalse.verified.txt
@@ -9,6 +9,7 @@
.WithBody("b")
)
.WithGuid("8e7b9ab7-e18e-4502-8bc9-11e6679811cc")
+ .WithProbability(0.3)
.RespondWith(Response.Create()
.WithHeader("Keep-Alive)", "test")
.WithBody("bbb")
diff --git a/test/WireMock.Net.Tests/Serialization/MappingConverterTests.ToCSharpCode_With_Builder_And_AddStartIsTrue.verified.txt b/test/WireMock.Net.Tests/Serialization/MappingConverterTests.ToCSharpCode_With_Builder_And_AddStartIsTrue.verified.txt
index 95b1a6c4..e742782b 100644
--- a/test/WireMock.Net.Tests/Serialization/MappingConverterTests.ToCSharpCode_With_Builder_And_AddStartIsTrue.verified.txt
+++ b/test/WireMock.Net.Tests/Serialization/MappingConverterTests.ToCSharpCode_With_Builder_And_AddStartIsTrue.verified.txt
@@ -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")
diff --git a/test/WireMock.Net.Tests/Serialization/MappingConverterTests.ToCSharpCode_With_Server_And_AddStartIsFalse.verified.txt b/test/WireMock.Net.Tests/Serialization/MappingConverterTests.ToCSharpCode_With_Server_And_AddStartIsFalse.verified.txt
index 779a9172..3d682ac9 100644
--- a/test/WireMock.Net.Tests/Serialization/MappingConverterTests.ToCSharpCode_With_Server_And_AddStartIsFalse.verified.txt
+++ b/test/WireMock.Net.Tests/Serialization/MappingConverterTests.ToCSharpCode_With_Server_And_AddStartIsFalse.verified.txt
@@ -9,6 +9,7 @@
.WithBody("b")
)
.WithGuid("8e7b9ab7-e18e-4502-8bc9-11e6679811cc")
+ .WithProbability(0.3)
.RespondWith(Response.Create()
.WithHeader("Keep-Alive)", "test")
.WithBody("bbb")
diff --git a/test/WireMock.Net.Tests/Serialization/MappingConverterTests.ToCSharpCode_With_Server_And_AddStartIsTrue.verified.txt b/test/WireMock.Net.Tests/Serialization/MappingConverterTests.ToCSharpCode_With_Server_And_AddStartIsTrue.verified.txt
index 894a8860..f215220d 100644
--- a/test/WireMock.Net.Tests/Serialization/MappingConverterTests.ToCSharpCode_With_Server_And_AddStartIsTrue.verified.txt
+++ b/test/WireMock.Net.Tests/Serialization/MappingConverterTests.ToCSharpCode_With_Server_And_AddStartIsTrue.verified.txt
@@ -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")
diff --git a/test/WireMock.Net.Tests/Serialization/MappingConverterTests.ToMappingModel_WithProbability_ReturnsCorrectModel.verified.txt b/test/WireMock.Net.Tests/Serialization/MappingConverterTests.ToMappingModel_WithProbability_ReturnsCorrectModel.verified.txt
new file mode 100644
index 00000000..9fab2fca
--- /dev/null
+++ b/test/WireMock.Net.Tests/Serialization/MappingConverterTests.ToMappingModel_WithProbability_ReturnsCorrectModel.verified.txt
@@ -0,0 +1,11 @@
+{
+ Guid: Guid_1,
+ UpdatedAt: DateTime_1,
+ Title: ,
+ Description: ,
+ Priority: 42,
+ Request: {},
+ Response: {},
+ UseWebhooksFireAndForget: false,
+ Probability: 0.4
+}
\ No newline at end of file
diff --git a/test/WireMock.Net.Tests/Serialization/MappingConverterTests.cs b/test/WireMock.Net.Tests/Serialization/MappingConverterTests.cs
index ec968b51..4e0f47a7 100644
--- a/test/WireMock.Net.Tests/Serialization/MappingConverterTests.cs
+++ b/test/WireMock.Net.Tests/Serialization/MappingConverterTests.cs
@@ -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
\ No newline at end of file
diff --git a/test/WireMock.Net.Tests/WireMockServerTests.WithProbability.cs b/test/WireMock.Net.Tests/WireMockServerTests.WithProbability.cs
new file mode 100644
index 00000000..e635a9cc
--- /dev/null
+++ b/test/WireMock.Net.Tests/WireMockServerTests.WithProbability.cs
@@ -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();
+ }
+}
\ No newline at end of file