Add Func<> matchhing. Solves issue #2

This commit is contained in:
Stef Heyenrath
2017-01-18 20:45:38 +01:00
parent 9d1fd8fd51
commit 65c17ff519
16 changed files with 321 additions and 118 deletions

View File

@@ -18,17 +18,26 @@ namespace WireMock.Net.ConsoleApplication
Console.WriteLine("FluentMockServer running at {0}", server.Port); Console.WriteLine("FluentMockServer running at {0}", server.Port);
server server
.Given( .Given(Request.WithUrl(u => u.Contains("x")).UsingGet())
Request .RespondWith(Response
.WithUrl("/*") .WithStatusCode(200)
.UsingGet() .WithHeader("Content-Type", "application/json")
) .WithBody(@"{ ""result"": ""/x with FUNC 200""}"));
.RespondWith(
Response server
.WithStatusCode(200) .Given(Request.WithUrl("/*").UsingGet())
.WithHeader("Content-Type", "application/json") .RespondWith(Response
.WithBody(@"{ ""msg"": ""Hello world!""}") .WithStatusCode(200)
); .WithHeader("Content-Type", "application/json")
.WithBody(@"{ ""msg"": ""Hello world!""}")
);
server
.Given(Request.WithUrl("/data").UsingPost().WithBody(b => b.Contains("e")))
.RespondWith(Response
.WithStatusCode(201)
.WithHeader("Content-Type", "application/json")
.WithBody(@"{ ""result"": ""data posted with FUNC 201""}"));
server server
.Given(Request.WithUrl("/data").UsingPost()) .Given(Request.WithUrl("/data").UsingPost())
@@ -42,12 +51,11 @@ namespace WireMock.Net.ConsoleApplication
.RespondWith(Response .RespondWith(Response
.WithStatusCode(200) .WithStatusCode(200)
.WithHeader("Content-Type", "application/json") .WithHeader("Content-Type", "application/json")
.WithBody(@"{ ""result"": ""data deleted with 201""}")); .WithBody(@"{ ""result"": ""data deleted with 200""}"));
Console.WriteLine("Press any key to stop the server"); Console.WriteLine("Press any key to stop the server");
Console.ReadKey(); Console.ReadKey();
Console.WriteLine("Displaying all requests"); Console.WriteLine("Displaying all requests");
var allRequests = server.RequestLogs; var allRequests = server.RequestLogs;
Console.WriteLine(JsonConvert.SerializeObject(allRequests, Formatting.Indented)); Console.WriteLine(JsonConvert.SerializeObject(allRequests, Formatting.Indented));

View File

@@ -1,16 +1,6 @@
using System.Diagnostics.CodeAnalysis; using System.Net;
using System.Net;
using System.Net.Sockets; using System.Net.Sockets;
[module:
SuppressMessage("StyleCop.CSharp.DocumentationRules",
"SA1633:FileMustHaveHeader",
Justification = "Reviewed. Suppression is OK here, as unknown copyright and company.")]
[module:
SuppressMessage("StyleCop.CSharp.DocumentationRules",
"SA1650:ElementDocumentationMustBeSpelledCorrectly",
Justification = "Reviewed. Suppression is OK here.")]
namespace WireMock.Http namespace WireMock.Http
{ {
/// <summary> /// <summary>
@@ -24,15 +14,21 @@ namespace WireMock.Http
/// <returns> /// <returns>
/// The <see cref="int"/>. /// The <see cref="int"/>.
/// </returns> /// </returns>
/// <remarks>see http://stackoverflow.com/questions/138043/find-the-next-tcp-port-in-net. </remarks> /// <remarks>see http://stackoverflow.com/questions/138043/find-the-next-tcp-port-in-net.</remarks>
// ReSharper disable once StyleCop.SA1650
public static int FindFreeTcpPort() public static int FindFreeTcpPort()
{ {
TcpListener l = new TcpListener(IPAddress.Loopback, 0); TcpListener tcpListener = null;
l.Start(); try
int port = ((IPEndPoint)l.LocalEndpoint).Port; {
l.Stop(); tcpListener = new TcpListener(IPAddress.Loopback, 0);
return port; tcpListener.Start();
return ((IPEndPoint)tcpListener.LocalEndpoint).Port;
}
finally
{
tcpListener?.Stop();
}
} }
} }
} }

View File

@@ -53,13 +53,6 @@ namespace WireMock.Http
{ {
_httpHandler = httpHandler; _httpHandler = httpHandler;
// .Net Framework is not supportted on XP or Server 2003, so no need for the check
/*if (!HttpListener.IsSupported)
{
Console.WriteLine("Windows XP SP2 or Server 2003 is required to use the HttpListener class.");
return;
}*/
// Create a listener. // Create a listener.
_listener = new HttpListener(); _listener = new HttpListener();
_listener.Prefixes.Add(urlPrefix); _listener.Prefixes.Add(urlPrefix);

View File

@@ -1,3 +1,4 @@
using System;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using JetBrains.Annotations; using JetBrains.Annotations;
@@ -29,6 +30,11 @@ namespace WireMock
/// </summary> /// </summary>
private readonly Regex bodyRegex; private readonly Regex bodyRegex;
/// <summary>
/// The body function
/// </summary>
private readonly Func<string, bool> bodyFunc;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="RequestBodySpec"/> class. /// Initializes a new instance of the <see cref="RequestBodySpec"/> class.
/// </summary> /// </summary>
@@ -41,6 +47,18 @@ namespace WireMock
bodyRegex = new Regex(body); bodyRegex = new Regex(body);
} }
/// <summary>
/// Initializes a new instance of the <see cref="RequestBodySpec"/> class.
/// </summary>
/// <param name="func">
/// The body func.
/// </param>
public RequestBodySpec([NotNull] Func<string, bool> func)
{
Check.NotNull(func, nameof(func));
bodyFunc = func;
}
/// <summary> /// <summary>
/// The is satisfied by. /// The is satisfied by.
/// </summary> /// </summary>
@@ -52,7 +70,7 @@ namespace WireMock
/// </returns> /// </returns>
public bool IsSatisfiedBy(RequestMessage requestMessage) public bool IsSatisfiedBy(RequestMessage requestMessage)
{ {
return bodyRegex.IsMatch(requestMessage.Body); return bodyRegex?.IsMatch(requestMessage.Body) ?? bodyFunc(requestMessage.Body);
} }
} }
} }

View File

@@ -1,4 +1,6 @@
namespace WireMock.RequestBuilders using System;
namespace WireMock.RequestBuilders
{ {
/// <summary> /// <summary>
/// The BodyRequestBuilder interface. /// The BodyRequestBuilder interface.
@@ -15,5 +17,16 @@
/// The <see cref="ISpecifyRequests"/>. /// The <see cref="ISpecifyRequests"/>.
/// </returns> /// </returns>
ISpecifyRequests WithBody(string body); ISpecifyRequests WithBody(string body);
/// <summary>
/// The with body.
/// </summary>
/// <param name="body">
/// The body function.
/// </param>
/// <returns>
/// The <see cref="ISpecifyRequests"/>.
/// </returns>
ISpecifyRequests WithBody(Func<string, bool> body);
} }
} }

View File

@@ -1,4 +1,8 @@
namespace WireMock.RequestBuilders using System;
using System.Collections.Generic;
using JetBrains.Annotations;
namespace WireMock.RequestBuilders
{ {
/// <summary> /// <summary>
/// The HeadersRequestBuilder interface. /// The HeadersRequestBuilder interface.
@@ -19,5 +23,16 @@
/// The <see cref="IHeadersRequestBuilder"/>. /// The <see cref="IHeadersRequestBuilder"/>.
/// </returns> /// </returns>
IHeadersRequestBuilder WithHeader(string name, string value, bool ignoreCase = true); IHeadersRequestBuilder WithHeader(string name, string value, bool ignoreCase = true);
/// <summary>
/// The with header.
/// </summary>
/// <param name="func">
/// The headers func.
/// </param>
/// <returns>
/// The <see cref="IHeadersRequestBuilder"/>.
/// </returns>
IHeadersRequestBuilder WithHeader([NotNull] Func<IDictionary<string, string>, bool> func);
} }
} }

View File

@@ -1,4 +1,8 @@
namespace WireMock.RequestBuilders using System;
using System.Collections.Generic;
using JetBrains.Annotations;
namespace WireMock.RequestBuilders
{ {
/// <summary> /// <summary>
/// The ParametersRequestBuilder interface. /// The ParametersRequestBuilder interface.
@@ -17,6 +21,17 @@
/// <returns> /// <returns>
/// The <see cref="ISpecifyRequests"/>. /// The <see cref="ISpecifyRequests"/>.
/// </returns> /// </returns>
ISpecifyRequests WithParam(string key, params string[] values); ISpecifyRequests WithParam([NotNull] string key, params string[] values);
/// <summary>
/// The with parameters.
/// </summary>
/// <param name="func">
/// The func.
/// </param>
/// <returns>
/// The <see cref="ISpecifyRequests"/>.
/// </returns>
ISpecifyRequests WithParam([NotNull] Func<IDictionary<string, List<string>>, bool> func);
} }
} }

View File

@@ -1,6 +1,8 @@
using System.Collections.Generic; using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.Linq; using System.Linq;
using JetBrains.Annotations;
[module: [module:
SuppressMessage("StyleCop.CSharp.ReadabilityRules", SuppressMessage("StyleCop.CSharp.ReadabilityRules",
@@ -54,10 +56,25 @@ namespace WireMock.RequestBuilders
/// </returns> /// </returns>
public static IVerbRequestBuilder WithUrl(string url) public static IVerbRequestBuilder WithUrl(string url)
{ {
var specs = new List<ISpecifyRequests>(); var specs = new List<ISpecifyRequests> { new RequestUrlSpec(url) };
var requests = new Request(specs);
specs.Add(new RequestUrlSpec(url)); return new Request(specs);
return requests; }
/// <summary>
/// The with url.
/// </summary>
/// <param name="func">
/// The url func.
/// </param>
/// <returns>
/// The <see cref="IVerbRequestBuilder"/>.
/// </returns>
public static IVerbRequestBuilder WithUrl(Func<string, bool> func)
{
var specs = new List<ISpecifyRequests> { new RequestUrlSpec(func) };
return new Request(specs);
} }
/// <summary> /// <summary>
@@ -71,10 +88,25 @@ namespace WireMock.RequestBuilders
/// </returns> /// </returns>
public static IVerbRequestBuilder WithPath(string path) public static IVerbRequestBuilder WithPath(string path)
{ {
var specs = new List<ISpecifyRequests>(); var specs = new List<ISpecifyRequests> { new RequestPathSpec(path) };
var requests = new Request(specs);
specs.Add(new RequestPathSpec(path)); return new Request(specs);
return requests; }
/// <summary>
/// The with path.
/// </summary>
/// <param name="func">
/// The path func.
/// </param>
/// <returns>
/// The <see cref="IVerbRequestBuilder"/>.
/// </returns>
public static IVerbRequestBuilder WithPath([NotNull] Func<string, bool> func)
{
var specs = new List<ISpecifyRequests> { new RequestPathSpec(func) };
return new Request(specs);
} }
/// <summary> /// <summary>
@@ -178,6 +210,21 @@ namespace WireMock.RequestBuilders
return this; return this;
} }
/// <summary>
/// The with body.
/// </summary>
/// <param name="func">
/// The body function.
/// </param>
/// <returns>
/// The <see cref="ISpecifyRequests"/>.
/// </returns>
public ISpecifyRequests WithBody(Func<string, bool> func)
{
_requestSpecs.Add(new RequestBodySpec(func));
return this;
}
/// <summary> /// <summary>
/// The with parameters. /// The with parameters.
/// </summary> /// </summary>
@@ -196,6 +243,21 @@ namespace WireMock.RequestBuilders
return this; return this;
} }
/// <summary>
/// The with parameters.
/// </summary>
/// <param name="func">
/// The func.
/// </param>
/// <returns>
/// The <see cref="ISpecifyRequests"/>.
/// </returns>
public ISpecifyRequests WithParam(Func<IDictionary<string, List<string>>, bool> func)
{
_requestSpecs.Add(new RequestParamSpec(func));
return this;
}
/// <summary> /// <summary>
/// The with header. /// The with header.
/// </summary> /// </summary>
@@ -214,5 +276,20 @@ namespace WireMock.RequestBuilders
_requestSpecs.Add(new RequestHeaderSpec(name, value, ignoreCase)); _requestSpecs.Add(new RequestHeaderSpec(name, value, ignoreCase));
return this; return this;
} }
/// <summary>
/// The with header.
/// </summary>
/// <param name="func">
/// The func.
/// </param>
/// <returns>
/// The <see cref="IHeadersRequestBuilder"/>.
/// </returns>
public IHeadersRequestBuilder WithHeader(Func<IDictionary<string, string>, bool> func)
{
_requestSpecs.Add(new RequestHeaderSpec(func));
return this;
}
} }
} }

View File

@@ -1,6 +1,9 @@
using System.Diagnostics.CodeAnalysis; using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using JetBrains.Annotations; using JetBrains.Annotations;
using WireMock.Validation;
[module: [module:
SuppressMessage("StyleCop.CSharp.ReadabilityRules", SuppressMessage("StyleCop.CSharp.ReadabilityRules",
@@ -33,6 +36,11 @@ namespace WireMock
/// </summary> /// </summary>
private readonly Regex patternRegex; private readonly Regex patternRegex;
/// <summary>
/// The header function
/// </summary>
private readonly Func<IDictionary<string, string>, bool> headerFunc;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="RequestHeaderSpec"/> class. /// Initializes a new instance of the <see cref="RequestHeaderSpec"/> class.
/// </summary> /// </summary>
@@ -49,6 +57,18 @@ namespace WireMock
patternRegex = ignoreCase ? new Regex(pattern, RegexOptions.IgnoreCase) : new Regex(pattern); patternRegex = ignoreCase ? new Regex(pattern, RegexOptions.IgnoreCase) : new Regex(pattern);
} }
/// <summary>
/// Initializes a new instance of the <see cref="RequestHeaderSpec"/> class.
/// </summary>
/// <param name="func">
/// The func.
/// </param>
public RequestHeaderSpec([NotNull] Func<IDictionary<string, string>, bool> func)
{
Check.NotNull(func, nameof(func));
headerFunc = func;
}
/// <summary> /// <summary>
/// The is satisfied by. /// The is satisfied by.
/// </summary> /// </summary>
@@ -58,8 +78,11 @@ namespace WireMock
/// <returns> /// <returns>
/// The <see cref="bool"/>. /// The <see cref="bool"/>.
/// </returns> /// </returns>
public bool IsSatisfiedBy([NotNull] RequestMessage requestMessage) public bool IsSatisfiedBy(RequestMessage requestMessage)
{ {
if (patternRegex == null)
return headerFunc(requestMessage.Headers);
string headerValue = requestMessage.Headers[name]; string headerValue = requestMessage.Headers[name];
return patternRegex.IsMatch(headerValue); return patternRegex.IsMatch(headerValue);
} }

View File

@@ -18,8 +18,7 @@ using System.Linq;
SuppressMessage("StyleCop.CSharp.DocumentationRules", SuppressMessage("StyleCop.CSharp.DocumentationRules",
"SA1650:ElementDocumentationMustBeSpelledCorrectly", "SA1650:ElementDocumentationMustBeSpelledCorrectly",
Justification = "Reviewed. Suppression is OK here.")] Justification = "Reviewed. Suppression is OK here.")]
// ReSharper disable ArrangeThisQualifier
// ReSharper disable InconsistentNaming
namespace WireMock namespace WireMock
{ {
/// <summary> /// <summary>
@@ -30,7 +29,7 @@ namespace WireMock
/// <summary> /// <summary>
/// The _params. /// The _params.
/// </summary> /// </summary>
private readonly Dictionary<string, List<string>> _params = new Dictionary<string, List<string>>(); private readonly IDictionary<string, List<string>> _params = new Dictionary<string, List<string>>();
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="RequestMessage"/> class. /// Initializes a new instance of the <see cref="RequestMessage"/> class.
@@ -50,7 +49,7 @@ namespace WireMock
/// <param name="headers"> /// <param name="headers">
/// The headers. /// The headers.
/// </param> /// </param>
public RequestMessage(string path, string query, string verb, string body, IDictionary<string, string> headers) public RequestMessage(string path, string query, string verb, string body, IDictionary<string, string> headers = null)
{ {
if (!string.IsNullOrEmpty(query)) if (!string.IsNullOrEmpty(query))
{ {
@@ -72,12 +71,14 @@ namespace WireMock
dict[key].Add(term.Split('=')[1]); dict[key].Add(term.Split('=')[1]);
return dict; return dict;
}); });
Parameters = _params;
} }
Path = path; Path = path;
Headers = headers; //.ToDictionary(kv => kv.Key.ToLower(), kv => kv.Value.ToLower()); Headers = headers;
Verb = verb.ToLower(); Verb = verb.ToLower();
Body = body?.Trim() ?? string.Empty; Body = body;
} }
/// <summary> /// <summary>
@@ -111,6 +112,11 @@ namespace WireMock
/// </summary> /// </summary>
public IDictionary<string, string> Headers { get; } public IDictionary<string, string> Headers { get; }
/// <summary>
/// Gets the parameters.
/// </summary>
public IDictionary<string, List<string>> Parameters { get; }
/// <summary> /// <summary>
/// Gets the body. /// Gets the body.
/// </summary> /// </summary>
@@ -130,4 +136,4 @@ namespace WireMock
return _params.ContainsKey(key) ? _params[key] : new List<string>(); return _params.ContainsKey(key) ? _params[key] : new List<string>();
} }
} }
} }

View File

@@ -1,7 +1,9 @@
using System.Collections.Generic; using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.Linq; using System.Linq;
using JetBrains.Annotations; using JetBrains.Annotations;
using WireMock.Validation;
[module: [module:
SuppressMessage("StyleCop.CSharp.ReadabilityRules", SuppressMessage("StyleCop.CSharp.ReadabilityRules",
@@ -15,8 +17,7 @@ using JetBrains.Annotations;
SuppressMessage("StyleCop.CSharp.DocumentationRules", SuppressMessage("StyleCop.CSharp.DocumentationRules",
"SA1633:FileMustHaveHeader", "SA1633:FileMustHaveHeader",
Justification = "Reviewed. Suppression is OK here, as unknown copyright and company.")] Justification = "Reviewed. Suppression is OK here, as unknown copyright and company.")]
// ReSharper disable ArrangeThisQualifier
// ReSharper disable InconsistentNaming
namespace WireMock namespace WireMock
{ {
/// <summary> /// <summary>
@@ -32,7 +33,9 @@ namespace WireMock
/// <summary> /// <summary>
/// The _values. /// The _values.
/// </summary> /// </summary>
private readonly List<string> _values; private readonly IEnumerable<string> _values;
private readonly Func<IDictionary<string, List<string>>, bool> _func;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="RequestParamSpec"/> class. /// Initializes a new instance of the <see cref="RequestParamSpec"/> class.
@@ -43,12 +46,27 @@ namespace WireMock
/// <param name="values"> /// <param name="values">
/// The values. /// The values.
/// </param> /// </param>
public RequestParamSpec(string key, List<string> values) public RequestParamSpec([NotNull] string key, [NotNull] IEnumerable<string> values)
{ {
Check.NotNull(key, nameof(key));
Check.NotNull(values, nameof(values));
_key = key; _key = key;
_values = values; _values = values;
} }
/// <summary>
/// Initializes a new instance of the <see cref="RequestParamSpec"/> class.
/// </summary>
/// <param name="func">
/// The func.
/// </param>
public RequestParamSpec([NotNull] Func<IDictionary<string, List<string>>, bool> func)
{
Check.NotNull(func, nameof(func));
_func = func;
}
/// <summary> /// <summary>
/// The is satisfied by. /// The is satisfied by.
/// </summary> /// </summary>
@@ -58,9 +76,14 @@ namespace WireMock
/// <returns> /// <returns>
/// The <see cref="bool"/>. /// The <see cref="bool"/>.
/// </returns> /// </returns>
public bool IsSatisfiedBy([NotNull] RequestMessage requestMessage) public bool IsSatisfiedBy(RequestMessage requestMessage)
{ {
return requestMessage.GetParameter(_key).Intersect(_values).Count() == _values.Count; if (_func != null)
{
return _func(requestMessage.Parameters);
}
return requestMessage.GetParameter(_key).Intersect(_values).Count() == _values.Count();
} }
} }
} }

View File

@@ -1,4 +1,5 @@
using System.Diagnostics.CodeAnalysis; using System;
using System.Diagnostics.CodeAnalysis;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using JetBrains.Annotations; using JetBrains.Annotations;
using WireMock.Validation; using WireMock.Validation;
@@ -15,8 +16,7 @@ using WireMock.Validation;
SuppressMessage("StyleCop.CSharp.DocumentationRules", SuppressMessage("StyleCop.CSharp.DocumentationRules",
"SA1633:FileMustHaveHeader", "SA1633:FileMustHaveHeader",
Justification = "Reviewed. Suppression is OK here, as unknown copyright and company.")] Justification = "Reviewed. Suppression is OK here, as unknown copyright and company.")]
// ReSharper disable ArrangeThisQualifier
// ReSharper disable InconsistentNaming
namespace WireMock namespace WireMock
{ {
/// <summary> /// <summary>
@@ -25,9 +25,14 @@ namespace WireMock
public class RequestPathSpec : ISpecifyRequests public class RequestPathSpec : ISpecifyRequests
{ {
/// <summary> /// <summary>
/// The _path. /// The pathRegex.
/// </summary> /// </summary>
private readonly Regex _path; private readonly Regex pathRegex;
/// <summary>
/// The url function
/// </summary>
private readonly Func<string, bool> pathFunc;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="RequestPathSpec"/> class. /// Initializes a new instance of the <see cref="RequestPathSpec"/> class.
@@ -38,7 +43,19 @@ namespace WireMock
public RequestPathSpec([NotNull, RegexPattern] string path) public RequestPathSpec([NotNull, RegexPattern] string path)
{ {
Check.NotNull(path, nameof(path)); Check.NotNull(path, nameof(path));
_path = new Regex(path); pathRegex = new Regex(path);
}
/// <summary>
/// Initializes a new instance of the <see cref="RequestPathSpec"/> class.
/// </summary>
/// <param name="func">
/// The url func.
/// </param>
public RequestPathSpec([NotNull] Func<string, bool> func)
{
Check.NotNull(func, nameof(func));
pathFunc = func;
} }
/// <summary> /// <summary>
@@ -50,9 +67,9 @@ namespace WireMock
/// <returns> /// <returns>
/// The <see cref="bool"/>. /// The <see cref="bool"/>.
/// </returns> /// </returns>
public bool IsSatisfiedBy([NotNull] RequestMessage requestMessage) public bool IsSatisfiedBy(RequestMessage requestMessage)
{ {
return _path.IsMatch(requestMessage.Path); return pathRegex?.IsMatch(requestMessage.Path) ?? pathFunc(requestMessage.Path);
} }
} }
} }

View File

@@ -1,4 +1,5 @@
using System.Diagnostics.CodeAnalysis; using System;
using System.Diagnostics.CodeAnalysis;
using JetBrains.Annotations; using JetBrains.Annotations;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using WireMock.Validation; using WireMock.Validation;
@@ -29,6 +30,11 @@ namespace WireMock
/// </summary> /// </summary>
private readonly Regex urlRegex; private readonly Regex urlRegex;
/// <summary>
/// The url function
/// </summary>
private readonly Func<string, bool> urlFunc;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="RequestUrlSpec"/> class. /// Initializes a new instance of the <see cref="RequestUrlSpec"/> class.
/// </summary> /// </summary>
@@ -41,6 +47,18 @@ namespace WireMock
urlRegex = new Regex(url); urlRegex = new Regex(url);
} }
/// <summary>
/// Initializes a new instance of the <see cref="RequestUrlSpec"/> class.
/// </summary>
/// <param name="func">
/// The url func.
/// </param>
public RequestUrlSpec(Func<string, bool> func)
{
Check.NotNull(func, nameof(func));
urlFunc = func;
}
/// <summary> /// <summary>
/// The is satisfied by. /// The is satisfied by.
/// </summary> /// </summary>
@@ -52,7 +70,7 @@ namespace WireMock
/// </returns> /// </returns>
public bool IsSatisfiedBy(RequestMessage requestMessage) public bool IsSatisfiedBy(RequestMessage requestMessage)
{ {
return urlRegex.IsMatch(requestMessage.Url); return urlRegex?.IsMatch(requestMessage.Url) ?? urlFunc(requestMessage.Url);
} }
} }
} }

View File

@@ -28,16 +28,6 @@ namespace WireMock
/// </summary> /// </summary>
private readonly IDictionary<string, string> _headers = new ConcurrentDictionary<string, string>(); private readonly IDictionary<string, string> _headers = new ConcurrentDictionary<string, string>();
/// <summary>
/// The status code.
/// </summary>
private volatile int statusCode = 200;
/// <summary>
/// The body.
/// </summary>
private volatile string body;
/// <summary> /// <summary>
/// Gets the headers. /// Gets the headers.
/// </summary> /// </summary>
@@ -46,34 +36,12 @@ namespace WireMock
/// <summary> /// <summary>
/// Gets or sets the status code. /// Gets or sets the status code.
/// </summary> /// </summary>
public int StatusCode public int StatusCode { get; set; } = 200;
{
get
{
return statusCode;
}
set
{
statusCode = value;
}
}
/// <summary> /// <summary>
/// Gets or sets the body. /// Gets or sets the body.
/// </summary> /// </summary>
public string Body public string Body { get; set; }
{
get
{
return body;
}
set
{
body = value;
}
}
/// <summary> /// <summary>
/// The add header. /// The add header.

View File

@@ -86,7 +86,7 @@ namespace WireMock.Net.Tests
Check.That(_server.RequestLogs).HasSize(1); Check.That(_server.RequestLogs).HasSize(1);
var requestLogged = _server.RequestLogs.First(); var requestLogged = _server.RequestLogs.First();
Check.That(requestLogged.Verb).IsEqualTo("get"); Check.That(requestLogged.Verb).IsEqualTo("get");
Check.That(requestLogged.Body).IsEmpty(); Check.That(requestLogged.Body).IsNull();
} }
[Test] [Test]

View File

@@ -265,6 +265,19 @@ namespace WireMock.Net.Tests
Check.That(spec.IsSatisfiedBy(request)).IsTrue(); Check.That(spec.IsSatisfiedBy(request)).IsTrue();
} }
[Test]
public void Should_specify_requests_matching_given_params_func()
{
// given
var spec = Request.WithPath("/foo").WithParam(p => p.ContainsKey("bar") && (p["bar"].Contains("1") || p["bar"].Contains("2")));
// when
var request = new RequestMessage("/foo", "bar=1&bar=2", "Get", "Hello world!", new Dictionary<string, string>());
// then
Check.That(spec.IsSatisfiedBy(request)).IsTrue();
}
[Test] [Test]
public void Should_exclude_requests_not_matching_given_params() public void Should_exclude_requests_not_matching_given_params()
{ {