diff --git a/src/WireMock.Net/DynamicResponseProvider.cs b/src/WireMock.Net/DynamicResponseProvider.cs deleted file mode 100644 index 1b227bb3..00000000 --- a/src/WireMock.Net/DynamicResponseProvider.cs +++ /dev/null @@ -1,62 +0,0 @@ -using System; -using System.Threading.Tasks; -using JetBrains.Annotations; -using WireMock.Validation; -using WireMock.Settings; - -namespace WireMock -{ - internal class DynamicResponseProvider : IResponseProvider - { - private readonly Func _responseMessageFunc; - - public DynamicResponseProvider([NotNull] Func responseMessageFunc) - { - Check.NotNull(responseMessageFunc, nameof(responseMessageFunc)); - - _responseMessageFunc = responseMessageFunc; - } - - public Task ProvideResponseAsync(RequestMessage requestMessage) - { - return Task.FromResult(_responseMessageFunc(requestMessage)); - } - } - - internal class DynamicAsyncResponseProvider : IResponseProvider - { - private readonly Func> _responseMessageFunc; - - public DynamicAsyncResponseProvider([NotNull] Func> responseMessageFunc) - { - Check.NotNull(responseMessageFunc, nameof(responseMessageFunc)); - - _responseMessageFunc = responseMessageFunc; - } - - public Task ProvideResponseAsync(RequestMessage requestMessage) - { - return _responseMessageFunc(requestMessage); - } - } - - internal class ProxyAsyncResponseProvider : IResponseProvider - { - private readonly Func> _responseMessageFunc; - private readonly IProxyAndRecordSettings _settings; - - public ProxyAsyncResponseProvider([NotNull] Func> responseMessageFunc, [NotNull] IProxyAndRecordSettings settings) - { - Check.NotNull(responseMessageFunc, nameof(responseMessageFunc)); - Check.NotNull(settings, nameof(settings)); - - _responseMessageFunc = responseMessageFunc; - _settings = settings; - } - - public Task ProvideResponseAsync(RequestMessage requestMessage) - { - return _responseMessageFunc(requestMessage, _settings); - } - } -} \ No newline at end of file diff --git a/src/WireMock.Net/Mapping.cs b/src/WireMock.Net/Mapping.cs index d0d9b352..8eb56d73 100644 --- a/src/WireMock.Net/Mapping.cs +++ b/src/WireMock.Net/Mapping.cs @@ -2,6 +2,7 @@ using System.Threading.Tasks; using JetBrains.Annotations; using WireMock.Matchers.Request; +using WireMock.ResponseProviders; namespace WireMock { diff --git a/src/WireMock.Net/ResponseBuilders/ICallbackResponseBuilder.cs b/src/WireMock.Net/ResponseBuilders/ICallbackResponseBuilder.cs new file mode 100644 index 00000000..bd06ef90 --- /dev/null +++ b/src/WireMock.Net/ResponseBuilders/ICallbackResponseBuilder.cs @@ -0,0 +1,19 @@ +using System; +using JetBrains.Annotations; +using WireMock.ResponseProviders; + +namespace WireMock.ResponseBuilders +{ + /// + /// The CallbackResponseBuilder interface. + /// + public interface ICallbackResponseBuilder : IResponseProvider + { + /// + /// The callback builder + /// + /// The . + [PublicAPI] + IResponseBuilder WithCallback([NotNull] Func callbackHandler); + } +} \ No newline at end of file diff --git a/src/WireMock.Net/ResponseBuilders/IDelayResponseBuilder.cs b/src/WireMock.Net/ResponseBuilders/IDelayResponseBuilder.cs index 458d3dd7..fe0d3b1c 100644 --- a/src/WireMock.Net/ResponseBuilders/IDelayResponseBuilder.cs +++ b/src/WireMock.Net/ResponseBuilders/IDelayResponseBuilder.cs @@ -5,7 +5,7 @@ namespace WireMock.ResponseBuilders /// /// The DelayResponseBuilder interface. /// - public interface IDelayResponseBuilder : IResponseProvider + public interface IDelayResponseBuilder : ICallbackResponseBuilder { /// /// The with delay. diff --git a/src/WireMock.Net/ResponseBuilders/Response.cs b/src/WireMock.Net/ResponseBuilders/Response.cs index 4e7d5d17..58cfe124 100644 --- a/src/WireMock.Net/ResponseBuilders/Response.cs +++ b/src/WireMock.Net/ResponseBuilders/Response.cs @@ -48,11 +48,13 @@ namespace WireMock.ResponseBuilders /// /// Gets the response message. /// - /// - /// The response message. - /// public ResponseMessage ResponseMessage { get; } + /// + /// A delegate to execute to generate the response + /// + public Func Callback { get; private set; } + /// /// Creates this instance. /// @@ -308,6 +310,16 @@ namespace WireMock.ResponseBuilders return WithProxy(settings.Url, settings.ClientX509Certificate2ThumbprintOrSubjectName); } + /// + public IResponseBuilder WithCallback(Func callbackHandler) + { + Check.NotNull(callbackHandler, nameof(callbackHandler)); + + Callback = callbackHandler; + + return this; + } + /// /// The provide response. /// @@ -336,6 +348,11 @@ namespace WireMock.ResponseBuilders return ResponseMessageTransformer.Transform(requestMessage, ResponseMessage); } + if (Callback != null) + { + return Callback(requestMessage); + } + return ResponseMessage; } } diff --git a/src/WireMock.Net/ResponseProviders/DynamicAsyncResponseProvider.cs b/src/WireMock.Net/ResponseProviders/DynamicAsyncResponseProvider.cs new file mode 100644 index 00000000..afbaa664 --- /dev/null +++ b/src/WireMock.Net/ResponseProviders/DynamicAsyncResponseProvider.cs @@ -0,0 +1,24 @@ +using System; +using System.Threading.Tasks; +using JetBrains.Annotations; +using WireMock.Validation; + +namespace WireMock.ResponseProviders +{ + internal class DynamicAsyncResponseProvider : IResponseProvider + { + private readonly Func> _responseMessageFunc; + + public DynamicAsyncResponseProvider([NotNull] Func> responseMessageFunc) + { + Check.NotNull(responseMessageFunc, nameof(responseMessageFunc)); + + _responseMessageFunc = responseMessageFunc; + } + + public Task ProvideResponseAsync(RequestMessage requestMessage) + { + return _responseMessageFunc(requestMessage); + } + } +} \ No newline at end of file diff --git a/src/WireMock.Net/ResponseProviders/DynamicResponseProvider.cs b/src/WireMock.Net/ResponseProviders/DynamicResponseProvider.cs new file mode 100644 index 00000000..d04b9fe5 --- /dev/null +++ b/src/WireMock.Net/ResponseProviders/DynamicResponseProvider.cs @@ -0,0 +1,24 @@ +using System; +using System.Threading.Tasks; +using JetBrains.Annotations; +using WireMock.Validation; + +namespace WireMock.ResponseProviders +{ + internal class DynamicResponseProvider : IResponseProvider + { + private readonly Func _responseMessageFunc; + + public DynamicResponseProvider([NotNull] Func responseMessageFunc) + { + Check.NotNull(responseMessageFunc, nameof(responseMessageFunc)); + + _responseMessageFunc = responseMessageFunc; + } + + public Task ProvideResponseAsync(RequestMessage requestMessage) + { + return Task.FromResult(_responseMessageFunc(requestMessage)); + } + } +} \ No newline at end of file diff --git a/src/WireMock.Net/IResponseProvider.cs b/src/WireMock.Net/ResponseProviders/IResponseProvider.cs similarity index 92% rename from src/WireMock.Net/IResponseProvider.cs rename to src/WireMock.Net/ResponseProviders/IResponseProvider.cs index 6643c9ca..38271f7d 100644 --- a/src/WireMock.Net/IResponseProvider.cs +++ b/src/WireMock.Net/ResponseProviders/IResponseProvider.cs @@ -1,7 +1,7 @@ using System.Threading.Tasks; using JetBrains.Annotations; -namespace WireMock +namespace WireMock.ResponseProviders { /// /// The Response Provider interface. diff --git a/src/WireMock.Net/ResponseProviders/ProxyAsyncResponseProvider.cs b/src/WireMock.Net/ResponseProviders/ProxyAsyncResponseProvider.cs new file mode 100644 index 00000000..f1283138 --- /dev/null +++ b/src/WireMock.Net/ResponseProviders/ProxyAsyncResponseProvider.cs @@ -0,0 +1,28 @@ +using System; +using System.Threading.Tasks; +using JetBrains.Annotations; +using WireMock.Settings; +using WireMock.Validation; + +namespace WireMock.ResponseProviders +{ + internal class ProxyAsyncResponseProvider : IResponseProvider + { + private readonly Func> _responseMessageFunc; + private readonly IProxyAndRecordSettings _settings; + + public ProxyAsyncResponseProvider([NotNull] Func> responseMessageFunc, [NotNull] IProxyAndRecordSettings settings) + { + Check.NotNull(responseMessageFunc, nameof(responseMessageFunc)); + Check.NotNull(settings, nameof(settings)); + + _responseMessageFunc = responseMessageFunc; + _settings = settings; + } + + public Task ProvideResponseAsync(RequestMessage requestMessage) + { + return _responseMessageFunc(requestMessage, _settings); + } + } +} \ No newline at end of file diff --git a/src/WireMock.Net/Server/FluentMockServer.Admin.cs b/src/WireMock.Net/Server/FluentMockServer.Admin.cs index d19d11db..9acb25e1 100644 --- a/src/WireMock.Net/Server/FluentMockServer.Admin.cs +++ b/src/WireMock.Net/Server/FluentMockServer.Admin.cs @@ -17,6 +17,7 @@ using WireMock.Matchers; using WireMock.Matchers.Request; using WireMock.RequestBuilders; using WireMock.ResponseBuilders; +using WireMock.ResponseProviders; using WireMock.Serialization; using WireMock.Settings; using WireMock.Util; diff --git a/src/WireMock.Net/Server/FluentMockServer.cs b/src/WireMock.Net/Server/FluentMockServer.cs index 63eb80c0..e1242858 100644 --- a/src/WireMock.Net/Server/FluentMockServer.cs +++ b/src/WireMock.Net/Server/FluentMockServer.cs @@ -14,6 +14,7 @@ using WireMock.RequestBuilders; using WireMock.Settings; using WireMock.Validation; using WireMock.Owin; +using WireMock.ResponseProviders; namespace WireMock.Server { diff --git a/src/WireMock.Net/Server/IRespondWithAProvider.cs b/src/WireMock.Net/Server/IRespondWithAProvider.cs index fd10623e..5e5391f1 100644 --- a/src/WireMock.Net/Server/IRespondWithAProvider.cs +++ b/src/WireMock.Net/Server/IRespondWithAProvider.cs @@ -1,4 +1,5 @@ using System; +using WireMock.ResponseProviders; namespace WireMock.Server { diff --git a/src/WireMock.Net/Server/RespondWithAProvider.cs b/src/WireMock.Net/Server/RespondWithAProvider.cs index bc7f50f2..8def27bd 100644 --- a/src/WireMock.Net/Server/RespondWithAProvider.cs +++ b/src/WireMock.Net/Server/RespondWithAProvider.cs @@ -1,5 +1,6 @@ using System; using WireMock.Matchers.Request; +using WireMock.ResponseProviders; namespace WireMock.Server { diff --git a/test/WireMock.Net.Tests/FluentMockServerTests.cs b/test/WireMock.Net.Tests/FluentMockServerTests.cs index 8568e7b8..3052c02b 100644 --- a/test/WireMock.Net.Tests/FluentMockServerTests.cs +++ b/test/WireMock.Net.Tests/FluentMockServerTests.cs @@ -89,13 +89,12 @@ namespace WireMock.Net.Tests } [Fact] - public void FluentMockServer_Admin_Mappings_Get() + public void FluentMockServer_Admin_Mappings_WithGuid_Get() { Guid guid = Guid.Parse("90356dba-b36c-469a-a17e-669cd84f1f05"); _server = FluentMockServer.Start(); - _server.Given(Request.Create().WithPath("/foo1").UsingGet()) - .WithGuid(guid) + _server.Given(Request.Create().WithPath("/foo1").UsingGet()).WithGuid(guid) .RespondWith(Response.Create().WithStatusCode(201).WithBody("1")); _server.Given(Request.Create().WithPath("/foo2").UsingGet()) @@ -105,6 +104,19 @@ namespace WireMock.Net.Tests Check.That(mappings).HasSize(2); } + [Fact] + public void FluentMockServer_Admin_Mappings_WithGuidAsString_Get() + { + string guid = "90356dba-b36c-469a-a17e-669cd84f1f05"; + _server = FluentMockServer.Start(); + + _server.Given(Request.Create().WithPath("/foo1").UsingGet()).WithGuid(guid) + .RespondWith(Response.Create().WithStatusCode(201).WithBody("1")); + + var mappings = _server.Mappings.ToArray(); + Check.That(mappings).HasSize(1); + } + [Fact] public void FluentMockServer_Admin_Mappings_Add_SameGuid() { @@ -432,6 +444,23 @@ namespace WireMock.Net.Tests Check.That(requestLoggedB.RequestMessage.Path).EndsWith("/foo3"); } + [Fact] + public async Task FluentMockServer_Should_respond_to_request_callback() + { + // Assign + _server = FluentMockServer.Start(); + + _server + .Given(Request.Create().WithPath("/foo").UsingGet()) + .RespondWith(Response.Create().WithCallback(req => new ResponseMessage { Body = req.Path + "Bar" })); + + // Act + string response = await new HttpClient().GetStringAsync("http://localhost:" + _server.Ports[0] + "/foo"); + + // Assert + Check.That(response).IsEqualTo("/fooBar"); + } + public void Dispose() { _server?.Stop(); diff --git a/test/WireMock.Net.Tests/Matchers/ExactObjectMatcherTests.cs b/test/WireMock.Net.Tests/Matchers/ExactObjectMatcherTests.cs new file mode 100644 index 00000000..abd9266f --- /dev/null +++ b/test/WireMock.Net.Tests/Matchers/ExactObjectMatcherTests.cs @@ -0,0 +1,23 @@ +using NFluent; +using WireMock.Matchers; +using Xunit; + +namespace WireMock.Net.Tests.Matchers +{ + public class ExactObjectMatcherTests + { + [Fact] + public void ExactObjectMatcher_GetName() + { + // Assign + object obj = 1; + + // Act + var matcher = new ExactObjectMatcher(obj); + string name = matcher.GetName(); + + // Assert + Check.That(name).Equals("ExactObjectMatcher"); + } + } +} \ No newline at end of file diff --git a/test/WireMock.Net.Tests/RequestWithBodyTests.cs b/test/WireMock.Net.Tests/RequestWithBodyTests.cs index 3287824f..ee22e936 100644 --- a/test/WireMock.Net.Tests/RequestWithBodyTests.cs +++ b/test/WireMock.Net.Tests/RequestWithBodyTests.cs @@ -15,6 +15,60 @@ namespace WireMock.Net.Tests { private const string ClientIp = "::1"; + [Fact] + public void Request_WithBody_FuncString() + { + // Assign + var requestBuilder = Request.Create().UsingAnyVerb().WithBody(b => b.Contains("b")); + + // Act + var body = new BodyData + { + BodyAsString = "b" + }; + var request = new RequestMessage(new Uri("http://localhost/foo"), "POST", ClientIp, body); + + // Assert + var requestMatchResult = new RequestMatchResult(); + Check.That(requestBuilder.GetMatchingScore(request, requestMatchResult)).IsEqualTo(1.0); + } + + [Fact] + public void Request_WithBody_FuncJson() + { + // Assign + var requestBuilder = Request.Create().UsingAnyVerb().WithBody(b => b != null); + + // Act + var body = new BodyData + { + BodyAsJson = 123 + }; + var request = new RequestMessage(new Uri("http://localhost/foo"), "POST", ClientIp, body); + + // Assert + var requestMatchResult = new RequestMatchResult(); + Check.That(requestBuilder.GetMatchingScore(request, requestMatchResult)).IsEqualTo(1.0); + } + + [Fact] + public void Request_WithBody_FuncByteArray() + { + // Assign + var requestBuilder = Request.Create().UsingAnyVerb().WithBody((byte[] b) => b != null); + + // Act + var body = new BodyData + { + BodyAsBytes = new byte[0] + }; + var request = new RequestMessage(new Uri("http://localhost/foo"), "POST", ClientIp, body); + + // Assert + var requestMatchResult = new RequestMatchResult(); + Check.That(requestBuilder.GetMatchingScore(request, requestMatchResult)).IsEqualTo(1.0); + } + [Fact] public void Request_WithBodyExactMatcher() { diff --git a/test/WireMock.Net.Tests/RequestWithClientIPTests.cs b/test/WireMock.Net.Tests/RequestWithClientIPTests.cs index 3381491f..4a73fe60 100644 --- a/test/WireMock.Net.Tests/RequestWithClientIPTests.cs +++ b/test/WireMock.Net.Tests/RequestWithClientIPTests.cs @@ -1,5 +1,6 @@ using System; using NFluent; +using WireMock.Matchers; using WireMock.Matchers.Request; using WireMock.RequestBuilders; using Xunit; @@ -35,5 +36,33 @@ namespace WireMock.Net.Tests var requestMatchResult = new RequestMatchResult(); Check.That(spec.GetMatchingScore(request, requestMatchResult)).IsEqualTo(0.0); } + + [Fact] + public void Request_WithClientIP_WildcardMatcher() + { + // given + var spec = Request.Create().WithClientIP(new WildcardMatcher("127.0.0.2")); + + // when + var request = new RequestMessage(new Uri("http://localhost"), "GET", "127.0.0.2"); + + // then + var requestMatchResult = new RequestMatchResult(); + Check.That(spec.GetMatchingScore(request, requestMatchResult)).IsEqualTo(1.0); + } + + [Fact] + public void Request_WithClientIP_Func() + { + // given + var spec = Request.Create().WithClientIP(c => c.Contains(".")); + + // when + var request = new RequestMessage(new Uri("http://localhost"), "GET", "127.0.0.2"); + + // then + var requestMatchResult = new RequestMatchResult(); + Check.That(spec.GetMatchingScore(request, requestMatchResult)).IsEqualTo(1.0); + } } } \ No newline at end of file diff --git a/test/WireMock.Net.Tests/RequestWithUrlTests.cs b/test/WireMock.Net.Tests/RequestWithUrlTests.cs index 054fe3c3..cad2210f 100644 --- a/test/WireMock.Net.Tests/RequestWithUrlTests.cs +++ b/test/WireMock.Net.Tests/RequestWithUrlTests.cs @@ -1,5 +1,6 @@ using System; using NFluent; +using WireMock.Matchers; using WireMock.Matchers.Request; using WireMock.RequestBuilders; using Xunit; @@ -25,10 +26,24 @@ namespace WireMock.Net.Tests } [Fact] - public void Request_WithUrlExact() + public void Request_WithUrl_WildcardMatcher() { // given - var spec = Request.Create().WithUrl("http://localhost/foo"); + var spec = Request.Create().WithUrl(new WildcardMatcher("*/foo")); + + // when + var request = new RequestMessage(new Uri("http://localhost/foo"), "blabla", ClientIp); + + // then + var requestMatchResult = new RequestMatchResult(); + Check.That(spec.GetMatchingScore(request, requestMatchResult)).IsEqualTo(1.0); + } + + [Fact] + public void Request_WithUrl_Func() + { + // given + var spec = Request.Create().WithUrl(url => url.Contains("foo")); // when var request = new RequestMessage(new Uri("http://localhost/foo"), "blabla", ClientIp);