diff --git a/README.md b/README.md index 8a5cab6c..7438f85e 100644 --- a/README.md +++ b/README.md @@ -13,9 +13,12 @@ The WireMock admin API provides functionality to define the mappings via a http ### /__admin/mappings The mappings defined in the mock service. * `GET /__admin/mappings` --> Gets all defined mappings -* `DELETE /__admin/mappings` --> Create a new stub mapping -* `POST /__admin/mappings` --> TODO +* `POST /__admin/mappings` --> Create a new stub mapping * `DELETE /__admin/mappings` --> TODO +* `GET /__admin/mappings/{guid}` --> Get a single stub mapping +* `PUT /__admin/mappings/{guid}` --> TODO +* `POST /__admin/mappings/{guid}` --> TODO +* `DELETE /__admin/mappings/{guid}` --> TODO ### /__admin/requests Logged requests and responses received by the mock service. diff --git a/src/WireMock.Net/Server/FluentMockServer.Admin.cs b/src/WireMock.Net/Server/FluentMockServer.Admin.cs index 233f0c99..6bf03e73 100644 --- a/src/WireMock.Net/Server/FluentMockServer.Admin.cs +++ b/src/WireMock.Net/Server/FluentMockServer.Admin.cs @@ -17,6 +17,9 @@ namespace WireMock.Server /// public partial class FluentMockServer { + private const string AdminMappings = "/__admin/mappings"; + private const string AdminRequests = "/__admin/requests"; + private readonly JsonSerializerSettings _settings = new JsonSerializerSettings { Formatting = Formatting.None, @@ -25,10 +28,27 @@ namespace WireMock.Server private void InitAdmin() { - Given(Request.Create().WithUrl("/__admin/mappings").UsingGet()).RespondWith(new DynamicResponseProvider(MappingsGet)); - Given(Request.Create().WithUrl("/__admin/mappings").UsingPost()).RespondWith(new DynamicResponseProvider(MappingsPost)); + // __admin/mappings + Given(Request.Create().WithUrl(AdminMappings).UsingGet()).RespondWith(new DynamicResponseProvider(MappingsGet)); + Given(Request.Create().WithUrl(AdminMappings).UsingPost()).RespondWith(new DynamicResponseProvider(MappingsPost)); - Given(Request.Create().WithUrl("/__admin/requests").UsingGet()).RespondWith(new DynamicResponseProvider(RequestsGet)); + // __admin/mappings/{guid} + var guidPathMatcher = new RegexMatcher(@"^\/__admin\/mappings\/(\{{0,1}([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}\}{0,1})$"); + Given(Request.Create().WithPath(guidPathMatcher).UsingGet()).RespondWith(new DynamicResponseProvider(MappingGet)); + + + // __admin/requests + Given(Request.Create().WithUrl(AdminRequests).UsingGet()).RespondWith(new DynamicResponseProvider(RequestsGet)); + } + + private ResponseMessage MappingGet(RequestMessage requestMessage) + { + Guid guid = Guid.Parse(requestMessage.Path.TrimStart(AdminMappings.ToCharArray())); + var mapping = Mappings.FirstOrDefault(m => !(m.Provider is DynamicResponseProvider) && m.Guid == guid); + + var model = ToMappingModel(mapping); + + return ToJson(model); } private ResponseMessage MappingsGet(RequestMessage requestMessage) @@ -248,7 +268,7 @@ namespace WireMock.Server switch (matcher.Name) { - case "RegExMatcher": + case "RegexMatcher": return new RegexMatcher(matcher.Pattern); case "JsonPathMatcher": diff --git a/src/WireMock.Net/Server/FluentMockServer.cs b/src/WireMock.Net/Server/FluentMockServer.cs index 2fd4dcbf..6b58605c 100644 --- a/src/WireMock.Net/Server/FluentMockServer.cs +++ b/src/WireMock.Net/Server/FluentMockServer.cs @@ -183,6 +183,13 @@ namespace WireMock.Server { lock (((ICollection)_mappings).SyncRoot) { + // Check a mapping exists with the same GUI, if so, remove it first. + var existingMapping = _mappings.FirstOrDefault(m => m.Guid == mapping.Guid); + if (existingMapping != null) + { + _mappings.Remove(existingMapping); + } + _mappings.Add(mapping); } } @@ -216,8 +223,8 @@ namespace WireMock.Server try { - var targetRoute = _mappings.FirstOrDefault(route => route.IsRequestHandled(request)); - if (targetRoute == null) + var targetMapping = _mappings.FirstOrDefault(route => route.IsRequestHandled(request)); + if (targetMapping == null) { response = new ResponseMessage { @@ -227,7 +234,7 @@ namespace WireMock.Server } else { - response = await targetRoute.ResponseTo(request); + response = await targetMapping.ResponseTo(request); } } catch (Exception ex) diff --git a/test/WireMock.Net.Tests/FluentMockServerTests.cs b/test/WireMock.Net.Tests/FluentMockServerTests.cs index db80df85..dcf4c433 100644 --- a/test/WireMock.Net.Tests/FluentMockServerTests.cs +++ b/test/WireMock.Net.Tests/FluentMockServerTests.cs @@ -20,7 +20,7 @@ namespace WireMock.Net.Tests private FluentMockServer _server; [Test] - public void FluentMockServer_get_routes() + public void FluentMockServer_Admin_Mappings_Get() { var guid = Guid.Parse("90356dba-b36c-469a-a17e-669cd84f1f05"); _server = FluentMockServer.Start(); @@ -32,16 +32,52 @@ namespace WireMock.Net.Tests _server.Given(Request.Create().WithUrl("/foo2").UsingGet()) .RespondWith(Response.Create().WithStatusCode(202).WithBody("2")); - var routes = _server.Mappings; + var mappings = _server.Mappings.ToArray(); + Check.That(mappings).HasSize(2); - var enumerable = routes.ToArray(); - Check.That(enumerable).HasSize(2); + Check.That(mappings.First().RequestMatcher).IsNotNull(); + Check.That(mappings.First().Provider).IsNotNull(); + Check.That(mappings.First().Guid).Equals(guid); - Check.That(enumerable.First().RequestMatcher).IsNotNull(); - Check.That(enumerable.First().Provider).IsNotNull(); - Check.That(enumerable.First().Guid).Equals(guid); + Check.That(mappings[1].Guid).Not.Equals(guid); + } - Check.That(enumerable[1].Guid).Not.Equals(guid); + [Test] + public void FluentMockServer_Admin_Mappings_Add_SameGuid() + { + var guid = Guid.Parse("90356dba-b36c-469a-a17e-669cd84f1f05"); + _server = FluentMockServer.Start(); + + _server.Given(Request.Create().WithUrl("/1").UsingGet()) + .WithGuid(guid) + .RespondWith(Response.Create().WithStatusCode(500)); + + var mappings = _server.Mappings.ToArray(); + Check.That(mappings).HasSize(1); + Check.That(mappings.First().Guid).Equals(guid); + + _server.Given(Request.Create().WithUrl("/2").UsingGet()) + .WithGuid(guid) + .RespondWith(Response.Create().WithStatusCode(500)); + + Check.That(mappings).HasSize(1); + Check.That(mappings.First().Guid).Equals(guid); + } + + [Test] + public async Task FluentMockServer_Admin_Requests_Get() + { + // given + _server = FluentMockServer.Start(); + + // when + await new HttpClient().GetAsync("http://localhost:" + _server.Port + "/foo"); + + // then + Check.That(_server.LogEntries).HasSize(1); + var requestLogged = _server.LogEntries.First(); + Check.That(requestLogged.RequestMessage.Method).IsEqualTo("get"); + Check.That(requestLogged.RequestMessage.BodyAsBytes).IsNull(); } [Test] @@ -94,22 +130,6 @@ namespace WireMock.Net.Tests Check.That((int)response.StatusCode).IsEqualTo(404); } - [Test] - public async Task Should_record_requests_in_the_requestlogs() - { - // given - _server = FluentMockServer.Start(); - - // when - await new HttpClient().GetAsync("http://localhost:" + _server.Port + "/foo"); - - // then - Check.That(_server.LogEntries).HasSize(1); - var requestLogged = _server.LogEntries.First(); - Check.That(requestLogged.RequestMessage.Method).IsEqualTo("get"); - Check.That(requestLogged.RequestMessage.BodyAsBytes).IsNull(); - } - [Test] public async Task Should_find_a_request_satisfying_a_request_spec() {