diff --git a/examples/WireMock.Net.ConsoleApplication/MainApp.cs b/examples/WireMock.Net.ConsoleApplication/MainApp.cs
index 1174af95..dd33505e 100644
--- a/examples/WireMock.Net.ConsoleApplication/MainApp.cs
+++ b/examples/WireMock.Net.ConsoleApplication/MainApp.cs
@@ -81,8 +81,29 @@ namespace WireMock.Net.ConsoleApplication
.WithParam("$filter", "(substringof(Code, 'WA')")
.UsingGet())
.RespondWith(Response.Create()
+ .WithHeader("Content-Type", "application/json")
.WithBody(@"{ ""result"": ""odata""}"));
+ server
+ .Given(Request
+ .Create()
+ .WithPath(new WildcardMatcher("/param2", true))
+ .WithParam("key", "test")
+ .UsingGet())
+ .RespondWith(Response.Create()
+ .WithHeader("Content-Type", "application/json")
+ .WithBodyAsJson(new { result = "param2" }));
+
+ server
+ .Given(Request
+ .Create()
+ .WithPath(new WildcardMatcher("/param3", true))
+ .WithParam("key", new WildcardMatcher("t*"))
+ .UsingGet())
+ .RespondWith(Response.Create()
+ .WithHeader("Content-Type", "application/json")
+ .WithBodyAsJson(new { result = "param3" }));
+
server
.Given(Request.Create().WithPath("/headers", "/headers_test").UsingPost().WithHeader("Content-Type", "application/json*"))
.RespondWith(Response.Create()
diff --git a/src/WireMock.Net/Admin/Mappings/ParamModel.cs b/src/WireMock.Net/Admin/Mappings/ParamModel.cs
index d118c734..1fe25043 100644
--- a/src/WireMock.Net/Admin/Mappings/ParamModel.cs
+++ b/src/WireMock.Net/Admin/Mappings/ParamModel.cs
@@ -1,4 +1,4 @@
-using System.Collections.Generic;
+// using System.Collections.Generic;
namespace WireMock.Admin.Mappings
{
@@ -12,10 +12,15 @@ namespace WireMock.Admin.Mappings
///
public string Name { get; set; }
+ /////
+ ///// Gets or sets the values.
+ /////
+ //public IList Values { get; set; }
+
///
- /// Gets or sets the values.
+ /// Gets or sets the matchers.
///
- public IList Values { get; set; }
+ public MatcherModel[] Matchers { get; set; }
/////
///// Gets or sets the functions.
diff --git a/src/WireMock.Net/Matchers/Request/RequestMessageParamMatcher.cs b/src/WireMock.Net/Matchers/Request/RequestMessageParamMatcher.cs
index be6fcee5..47b4fe74 100644
--- a/src/WireMock.Net/Matchers/Request/RequestMessageParamMatcher.cs
+++ b/src/WireMock.Net/Matchers/Request/RequestMessageParamMatcher.cs
@@ -25,16 +25,16 @@ namespace WireMock.Matchers.Request
public string Key { get; }
///
- /// The values
+ /// The matchers.
///
- public IEnumerable Values { get; }
+ public IReadOnlyList Matchers { get; }
///
/// Initializes a new instance of the class.
///
/// The match behaviour.
/// The key.
- public RequestMessageParamMatcher(MatchBehaviour matchBehaviour, [NotNull] string key) : this(matchBehaviour, key, null)
+ public RequestMessageParamMatcher(MatchBehaviour matchBehaviour, [NotNull] string key) : this(matchBehaviour, key, (IStringMatcher[])null)
{
}
@@ -44,13 +44,23 @@ namespace WireMock.Matchers.Request
/// The match behaviour.
/// The key.
/// The values.
- public RequestMessageParamMatcher(MatchBehaviour matchBehaviour, [NotNull] string key, [CanBeNull] IEnumerable values)
+ public RequestMessageParamMatcher(MatchBehaviour matchBehaviour, [NotNull] string key, [CanBeNull] string[] values) : this(matchBehaviour, key, values?.Select(value => new ExactMatcher(matchBehaviour, value)).Cast().ToArray())
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The match behaviour.
+ /// The key.
+ /// The matchers.
+ public RequestMessageParamMatcher(MatchBehaviour matchBehaviour, [NotNull] string key, [CanBeNull] IStringMatcher[] matchers)
{
Check.NotNull(key, nameof(key));
_matchBehaviour = matchBehaviour;
Key = key;
- Values = values;
+ Matchers = matchers;
}
///
@@ -78,21 +88,33 @@ namespace WireMock.Matchers.Request
return MatchScores.ToScore(requestMessage.Query != null && Funcs.Any(f => f(requestMessage.Query)));
}
- var values = requestMessage.GetParameter(Key);
- if (values == null)
+ WireMockList valuesPresentInRequestMessage = requestMessage.GetParameter(Key);
+ if (valuesPresentInRequestMessage == null)
{
- // Key is not present, just return Mismatch
+ // Key is not present at all, just return Mismatch
return MatchScores.Mismatch;
}
- if (values.Count == 0 && (Values == null || !Values.Any()))
+ if (Matchers != null && Matchers.Any())
{
- // Key is present, but no values or null, just return Perfect
+ // Matchers are defined, just use the matchers to calculate the match score.
+ var scores = new List();
+ foreach (string valuePresentInRequestMessage in valuesPresentInRequestMessage)
+ {
+ double score = Matchers.Max(m => m.IsMatch(valuePresentInRequestMessage));
+ scores.Add(score);
+ }
+
+ return scores.Any() ? scores.Average() : MatchScores.Mismatch;
+ }
+
+ if (Matchers == null || !Matchers.Any())
+ {
+ // Matchers are null or not defined, and Key is present, just return Perfect.
return MatchScores.Perfect;
}
- var matches = Values.Select(v => values.Contains(v));
- return MatchScores.ToScore(matches);
+ return MatchScores.Mismatch;
}
}
}
\ No newline at end of file
diff --git a/src/WireMock.Net/RequestBuilders/IParamsRequestBuilder.cs b/src/WireMock.Net/RequestBuilders/IParamsRequestBuilder.cs
index 0194de0c..ddb21610 100644
--- a/src/WireMock.Net/RequestBuilders/IParamsRequestBuilder.cs
+++ b/src/WireMock.Net/RequestBuilders/IParamsRequestBuilder.cs
@@ -27,6 +27,14 @@ namespace WireMock.RequestBuilders
/// The .
IRequestBuilder WithParam([NotNull] string key, [CanBeNull] params string[] values);
+ ///
+ /// WithParam: matching on key and matchers.
+ ///
+ /// The key.
+ /// The matchers.
+ /// The .
+ IRequestBuilder WithParam([NotNull] string key, [CanBeNull] params IStringMatcher[] matchers);
+
///
/// WithParam: matching on key, values and matchBehaviour.
///
@@ -36,6 +44,15 @@ namespace WireMock.RequestBuilders
/// The .
IRequestBuilder WithParam([NotNull] string key, MatchBehaviour matchBehaviour, [CanBeNull] params string[] values);
+ ///
+ /// WithParam: matching on key, matchers and matchBehaviour.
+ ///
+ /// The key.
+ /// The matchers.
+ /// The match behaviour.
+ /// The .
+ IRequestBuilder WithParam([NotNull] string key, MatchBehaviour matchBehaviour, [CanBeNull] params IStringMatcher[] matchers);
+
///
/// WithParam: matching on functions.
///
diff --git a/src/WireMock.Net/RequestBuilders/Request.cs b/src/WireMock.Net/RequestBuilders/Request.cs
index 2cb36900..787c2179 100644
--- a/src/WireMock.Net/RequestBuilders/Request.cs
+++ b/src/WireMock.Net/RequestBuilders/Request.cs
@@ -306,6 +306,12 @@ namespace WireMock.RequestBuilders
return WithParam(key, MatchBehaviour.AcceptOnMatch, values);
}
+ ///
+ public IRequestBuilder WithParam(string key, params IStringMatcher[] matchers)
+ {
+ return WithParam(key, MatchBehaviour.AcceptOnMatch, matchers);
+ }
+
///
public IRequestBuilder WithParam(string key, MatchBehaviour matchBehaviour, params string[] values)
{
@@ -315,6 +321,15 @@ namespace WireMock.RequestBuilders
return this;
}
+ ///
+ public IRequestBuilder WithParam(string key, MatchBehaviour matchBehaviour, params IStringMatcher[] matchers)
+ {
+ Check.NotNull(key, nameof(key));
+
+ _requestMatchers.Add(new RequestMessageParamMatcher(matchBehaviour, key, matchers));
+ return this;
+ }
+
///
public IRequestBuilder WithParam(params Func>, bool>[] funcs)
{
diff --git a/src/WireMock.Net/Serialization/MappingConverter.cs b/src/WireMock.Net/Serialization/MappingConverter.cs
index 26c4b948..6f7d6c9b 100644
--- a/src/WireMock.Net/Serialization/MappingConverter.cs
+++ b/src/WireMock.Net/Serialization/MappingConverter.cs
@@ -71,7 +71,7 @@ namespace WireMock.Serialization
Params = paramsMatchers != null && paramsMatchers.Any() ? paramsMatchers.Select(pm => new ParamModel
{
Name = pm.Key,
- Values = pm.Values?.ToList()
+ Matchers = MatcherMapper.Map(pm.Matchers)
//Funcs = Map(pm.Funcs)
}).ToList() : null,
diff --git a/src/WireMock.Net/Server/FluentMockServer.Admin.cs b/src/WireMock.Net/Server/FluentMockServer.Admin.cs
index 1401bf9b..13aecb41 100644
--- a/src/WireMock.Net/Server/FluentMockServer.Admin.cs
+++ b/src/WireMock.Net/Server/FluentMockServer.Admin.cs
@@ -618,9 +618,9 @@ namespace WireMock.Server
if (requestModel.Params != null)
{
- foreach (var paramModel in requestModel.Params)
+ foreach (var paramModel in requestModel.Params.Where(c => c.Matchers != null))
{
- requestBuilder = paramModel.Values == null ? requestBuilder.WithParam(paramModel.Name) : requestBuilder.WithParam(paramModel.Name, paramModel.Values.ToArray());
+ requestBuilder = requestBuilder.WithParam(paramModel.Name, paramModel.Matchers.Select(MatcherMapper.Map).Cast().ToArray());
}
}
diff --git a/test/WireMock.Net.Tests/RequestMatchers/RequestMessageParamMatcherTests.cs b/test/WireMock.Net.Tests/RequestMatchers/RequestMessageParamMatcherTests.cs
index fa119662..e464bc8b 100644
--- a/test/WireMock.Net.Tests/RequestMatchers/RequestMessageParamMatcherTests.cs
+++ b/test/WireMock.Net.Tests/RequestMatchers/RequestMessageParamMatcherTests.cs
@@ -9,7 +9,7 @@ namespace WireMock.Net.Tests.RequestMatchers
public class RequestMessageParamMatcherTests
{
[Fact]
- public void RequestMessageParamMatcher_GetMatchingScore_AllMatch()
+ public void RequestMessageParamMatcher_GetMatchingScore_KeyWithValuesPresentInUrl_MatchExactOnStringValues()
{
// Assign
var requestMessage = new RequestMessage(new Uri("http://localhost?key=test1,test2"), "GET", "127.0.0.1");
@@ -24,7 +24,22 @@ namespace WireMock.Net.Tests.RequestMatchers
}
[Fact]
- public void RequestMessageParamMatcher_GetMatchingScore_PartialMatch()
+ public void RequestMessageParamMatcher_GetMatchingScore_KeyWithValuesPresentInUrl_MatchExactOnExactMatchers()
+ {
+ // Assign
+ var requestMessage = new RequestMessage(new Uri("http://localhost?key=test1,test2"), "GET", "127.0.0.1");
+ var matcher = new RequestMessageParamMatcher(MatchBehaviour.AcceptOnMatch, "key", new IStringMatcher[] { new ExactMatcher("test1"), new ExactMatcher("test2") });
+
+ // Act
+ var result = new RequestMatchResult();
+ double score = matcher.GetMatchingScore(requestMessage, result);
+
+ // Assert
+ Check.That(score).IsEqualTo(1.0d);
+ }
+
+ [Fact]
+ public void RequestMessageParamMatcher_GetMatchingScore_KeyWithValuesPresentInUrl_MatchOnKeyWithValues_PartialMatch()
{
// Assign
var requestMessage = new RequestMessage(new Uri("http://localhost?key=test0,test2"), "GET", "127.0.0.1");
@@ -39,7 +54,7 @@ namespace WireMock.Net.Tests.RequestMatchers
}
[Fact]
- public void RequestMessageParamMatcher_GetMatchingScore_OnlyKeyPresent()
+ public void RequestMessageParamMatcher_GetMatchingScore_OnlyKeyPresentInUrl_MatchOnKeyWithValues_Fails()
{
// Assign
var requestMessage = new RequestMessage(new Uri("http://localhost?key"), "GET", "127.0.0.1");
@@ -54,7 +69,7 @@ namespace WireMock.Net.Tests.RequestMatchers
}
[Fact]
- public void RequestMessageParamMatcher_GetMatchingScore_OnlyKeyPresent_WithNull()
+ public void RequestMessageParamMatcher_GetMatchingScore_OnlyKeyPresentInUrl_MatchOnKey()
{
// Assign
var requestMessage = new RequestMessage(new Uri("http://localhost?key"), "GET", "127.0.0.1");
@@ -69,7 +84,7 @@ namespace WireMock.Net.Tests.RequestMatchers
}
[Fact]
- public void RequestMessageParamMatcher_GetMatchingScore_OnlyKeyPresent_WithEmptyArray()
+ public void RequestMessageParamMatcher_GetMatchingScore_OnlyKeyPresentInUrl_MatchOnKeyWithEmptyArray()
{
// Assign
var requestMessage = new RequestMessage(new Uri("http://localhost?key"), "GET", "127.0.0.1");
@@ -82,5 +97,20 @@ namespace WireMock.Net.Tests.RequestMatchers
// Assert
Check.That(score).IsEqualTo(1.0d);
}
+
+ [Fact]
+ public void RequestMessageParamMatcher_GetMatchingScore_KeyWithValuePresentInUrl_MatchOnKey()
+ {
+ // Assign
+ var requestMessage = new RequestMessage(new Uri("http://localhost?key=frank@contoso.com"), "GET", "127.0.0.1");
+ var matcher = new RequestMessageParamMatcher(MatchBehaviour.AcceptOnMatch, "key");
+
+ // Act
+ var result = new RequestMatchResult();
+ double score = matcher.GetMatchingScore(requestMessage, result);
+
+ // Assert
+ Check.That(score).IsEqualTo(1.0d);
+ }
}
}
\ No newline at end of file