From c7fe5ab7825e0774eacae5cab02ea895412d8932 Mon Sep 17 00:00:00 2001 From: Stef Heyenrath Date: Wed, 28 Feb 2018 20:51:39 +0100 Subject: [PATCH 1/2] Callback --- src/WireMock.Net/DynamicResponseProvider.cs | 62 ------------------- src/WireMock.Net/Mapping.cs | 1 + .../ICallbackResponseBuilder.cs | 19 ++++++ .../ResponseBuilders/IDelayResponseBuilder.cs | 2 +- src/WireMock.Net/ResponseBuilders/Response.cs | 23 ++++++- .../DynamicAsyncResponseProvider.cs | 24 +++++++ .../DynamicResponseProvider.cs | 24 +++++++ .../IResponseProvider.cs | 2 +- .../ProxyAsyncResponseProvider.cs | 28 +++++++++ .../Server/FluentMockServer.Admin.cs | 1 + src/WireMock.Net/Server/FluentMockServer.cs | 1 + .../Server/IRespondWithAProvider.cs | 1 + .../Server/RespondWithAProvider.cs | 1 + .../FluentMockServerTests.cs | 17 +++++ 14 files changed, 139 insertions(+), 67 deletions(-) delete mode 100644 src/WireMock.Net/DynamicResponseProvider.cs create mode 100644 src/WireMock.Net/ResponseBuilders/ICallbackResponseBuilder.cs create mode 100644 src/WireMock.Net/ResponseProviders/DynamicAsyncResponseProvider.cs create mode 100644 src/WireMock.Net/ResponseProviders/DynamicResponseProvider.cs rename src/WireMock.Net/{ => ResponseProviders}/IResponseProvider.cs (93%) create mode 100644 src/WireMock.Net/ResponseProviders/ProxyAsyncResponseProvider.cs diff --git a/src/WireMock.Net/DynamicResponseProvider.cs b/src/WireMock.Net/DynamicResponseProvider.cs deleted file mode 100644 index 1b227bb35..000000000 --- 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 d0d9b3523..8eb56d734 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 000000000..bd06ef902 --- /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 458d3dd75..fe0d3b1c3 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 4e7d5d17b..58cfe124f 100644 --- a/src/WireMock.Net/ResponseBuilders/Response.cs +++ b/src/WireMock.Net/ResponseBuilders/Response.cs @@ -48,11 +48,13 @@ public class Response : IResponseBuilder /// /// 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 @@ public IResponseBuilder WithProxy(IProxyAndRecordSettings settings) 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 @@ public async Task ProvideResponseAsync(RequestMessage requestMe 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 000000000..afbaa6647 --- /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 000000000..d04b9fe5c --- /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 93% rename from src/WireMock.Net/IResponseProvider.cs rename to src/WireMock.Net/ResponseProviders/IResponseProvider.cs index 6643c9ca4..38271f7de 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 000000000..f1283138a --- /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 d19d11db1..9acb25e18 100644 --- a/src/WireMock.Net/Server/FluentMockServer.Admin.cs +++ b/src/WireMock.Net/Server/FluentMockServer.Admin.cs @@ -17,6 +17,7 @@ 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 63eb80c0b..e1242858f 100644 --- a/src/WireMock.Net/Server/FluentMockServer.cs +++ b/src/WireMock.Net/Server/FluentMockServer.cs @@ -14,6 +14,7 @@ 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 fd10623ee..5e5391f1b 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 bc7f50f2d..8def27bdb 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 8568e7b83..70f74d038 100644 --- a/test/WireMock.Net.Tests/FluentMockServerTests.cs +++ b/test/WireMock.Net.Tests/FluentMockServerTests.cs @@ -432,6 +432,23 @@ public async Task FluentMockServer_Logging_SetMaxRequestLogCount() 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(); From 2ddd0257b9da71331ed4da4dfb90afcbb3b2b6e2 Mon Sep 17 00:00:00 2001 From: Stef Heyenrath Date: Thu, 1 Mar 2018 18:21:32 +0100 Subject: [PATCH 2/2] Add more tests --- .../FluentMockServerTests.cs | 18 +++++-- .../Matchers/ExactObjectMatcherTests.cs | 23 ++++++++ .../RequestWithBodyTests.cs | 54 +++++++++++++++++++ .../RequestWithClientIPTests.cs | 29 ++++++++++ .../WireMock.Net.Tests/RequestWithUrlTests.cs | 19 ++++++- 5 files changed, 138 insertions(+), 5 deletions(-) create mode 100644 test/WireMock.Net.Tests/Matchers/ExactObjectMatcherTests.cs diff --git a/test/WireMock.Net.Tests/FluentMockServerTests.cs b/test/WireMock.Net.Tests/FluentMockServerTests.cs index 70f74d038..3052c02b1 100644 --- a/test/WireMock.Net.Tests/FluentMockServerTests.cs +++ b/test/WireMock.Net.Tests/FluentMockServerTests.cs @@ -89,13 +89,12 @@ public void FluentMockServer_ReadStaticMappings() } [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 @@ public void FluentMockServer_Admin_Mappings_Get() 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() { diff --git a/test/WireMock.Net.Tests/Matchers/ExactObjectMatcherTests.cs b/test/WireMock.Net.Tests/Matchers/ExactObjectMatcherTests.cs new file mode 100644 index 000000000..abd9266f8 --- /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 3287824f2..ee22e936a 100644 --- a/test/WireMock.Net.Tests/RequestWithBodyTests.cs +++ b/test/WireMock.Net.Tests/RequestWithBodyTests.cs @@ -15,6 +15,60 @@ public class RequestWithBodyTests { 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 3381491f4..4a73fe60f 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 @@ public void Request_WithClientIP_Match_Fail() 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 054fe3c36..cad2210fd 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 @@ public void Request_WithUrl() } [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);