{"id":614,"date":"2016-02-25T20:44:35","date_gmt":"2016-02-25T20:44:35","guid":{"rendered":"http:\/\/tpodolak.com\/blog\/?p=614"},"modified":"2017-04-09T16:40:56","modified_gmt":"2017-04-09T16:40:56","slug":"mocking-downstream-services-mountebank","status":"publish","type":"post","link":"https:\/\/tpodolak.com\/blog\/2016\/02\/25\/mocking-downstream-services-mountebank\/","title":{"rendered":"Mocking downstream services with Mountebank"},"content":{"rendered":"<h3>1. Introduction<\/h3>\n<p>I&#8217;m a part of a team which creates large enterprise platform for the banking sector. Due to the fact that we operate in the financial area, our application consumes a high amount of downstream services. One of the major problems we are facing at the moment is the inaccessibility of those services on <i>DEV<\/i> and <i>UAT<\/i> environments. It often happens that one of those services is down for quite some time, so our development speed is impaired. The bigger problem, however, is the fact that our end-to-end tests are red. Having a red test on <i>TeamCity<\/i> for a long time is a really annoying thing because basically at this point, we just automatically assume that all of the failures are caused by issues with downstream systems. Fortunately, we finally decided to get rid of this problem and this is the solution we came up with. <\/p>\n<h3>2. Background<\/h3>\n<p>Before I go to the implementation details, take a look at a sample implementation of situation I described at the very beginning. Let&#8217;s assume that we have <i>WCF<\/i> service which contains business logic of our application and it is consumed by the <i>UI<\/i> side<\/p>\n<pre lang=\"csharp\">\r\npublic class BookingFacade :  IBookingFacade\r\n{\r\n    public Response<Price> Price(Models.GetPriceRequest request)\r\n    {\r\n        \/\/ in real life scenario Pricer should be injected\r\n        var pricerService = new Pricer();\r\n        var response = new Response<Price>();\r\n        try\r\n        {\r\n            var tradingDates = pricerService.GetTradingDates();\r\n            var price = pricerService.GetPrice(new GetPriceRequest\r\n            {\r\n                IsAdvised = request.IsAdvised\r\n            });\r\n\r\n            \/\/ rest of the code omitted for brevity\r\n            response.Result = new Price\r\n            {\r\n                TradingDates = new TradingDates\r\n                {\r\n                    MaturityDate = tradingDates.MaturityDate,\r\n                    SettlementDate = tradingDates.SettlementDate\r\n                }\r\n            };\r\n            \/\/ rest of the code omitted for brevity\r\n        }\r\n        catch (Exception ex)\r\n        {\r\n            \/\/ rest of the code omitted for brevity\r\n        }\r\n        return response;\r\n    }\r\n}\r\n<\/pre>\n<p><i>BookingFacade<\/i> uses <i>Pricer<\/i> service which basically is just a wrapper for external\/downstream service we have to use in order to retrieve some data (and we do not have an ownership of that service).<\/p>\n<pre lang=\"csharp\">\r\npublic class Pricer : IPricer\r\n{\r\n    public TradingDates GetTradingDates()\r\n    {\r\n        using (var webClient = new WebClient())\r\n        {\r\n            var result = webClient.DownloadString(ConfigurationManager.AppSettings[\"MockingDownstreamServices.Externals.Pricer.GetTradingDates\"]);\r\n            return JsonConvert.DeserializeObject<TradingDates>(result);\r\n        }\r\n\r\n    public Price GetPrice(GetPriceRequest request)\r\n    {\r\n        using (var webClient = new WebClient())\r\n        {\r\n            var result = webClient.UploadString(ConfigurationManager.AppSettings[\"MockingDownstreamServices.Externals.Pricer.GetPrice\"], JsonConvert.SerializeObject(request));\r\n            return JsonConvert.DeserializeObject<Price>(result);\r\n        }\r\n    }\r\n}\r\n<\/pre>\n<p>Very simple end-to-end test for <i>BookingFacade<\/i> can look like that<\/p>\n<pre class=\"csharp\">\r\n[TestFixture]\r\npublic class BookingFacadeTests\r\n{\r\n    [Test]\r\n    public void CanSuccessfullyPriceTest()\r\n    {\r\n        var response = this.Price(new GetPriceRequest());\r\n        Assert.IsNotNull(response);\r\n        Assert.IsNotNull(response.Result);\r\n        Assert.IsFalse(string.IsNullOrWhiteSpace(response.Result.Id));\r\n        CollectionAssert.IsEmpty(response.Messages.Where(val => val.StatusCode == StatusCodes.Error));\r\n    }\r\n}\r\n<\/pre>\n<p>As I mentioned before, everything is fine as long as all of the downstream systems are working. The moment one of them is down, our tests start failing.<br \/>\n<a href=\"\/\/tpodolak.com\/blog\/wp-content\/uploads\/2016\/02\/mocking-downstream-services-with-mountebank-part-one\/FailingTests.png\" rel=\"attachment wp-att-624\"><img decoding=\"async\" src=\"\/\/tpodolak.com\/blog\/wp-content\/uploads\/2016\/02\/mocking-downstream-services-with-mountebank-part-one\/FailingTests.png\" alt=\"FailingTests\" width=\"700\" class=\"aligncenter size-full wp-image-624\" srcset=\"https:\/\/tpodolak.com\/blog\/wp-content\/uploads\/2016\/02\/mocking-downstream-services-with-mountebank-part-one\/FailingTests.png 975w, https:\/\/tpodolak.com\/blog\/wp-content\/uploads\/2016\/02\/mocking-downstream-services-with-mountebank-part-one\/FailingTests-150x68.png 150w, https:\/\/tpodolak.com\/blog\/wp-content\/uploads\/2016\/02\/mocking-downstream-services-with-mountebank-part-one\/FailingTests-300x136.png 300w\" sizes=\"(max-width: 975px) 100vw, 975px\" \/><\/a><\/p>\n<h3>3. Implementation<\/h3>\n<p>General idea to fix this problem is to use fake downstream systems during end-to-end testing. In order to do that we use combination of custom compilation profile, <i>app.config<\/i> transformations and  <a href=\"http:\/\/www.mbtest.org\/\">mountebank<\/a> test doubles.  <\/p>\n<h4>3.1 Setting up transformations<\/h4>\n<p>First of all we will create a custom compilation profile called <i>test.integration<\/i> which will be used for running tests with mocked downstream systems (we want to preserve the normal use of downstreams for <i>Debug<\/i> and <i>Release<\/i> mode). In order to do that, go to <i>ConfigurationManager<\/i><br \/>\n<a href=\"\/\/tpodolak.com\/blog\/wp-content\/uploads\/2016\/02\/mocking-downstream-services-with-mountebank-part-one\/ConfigurationManager.png\" rel=\"attachment wp-att-620\"><img decoding=\"async\" src=\"\/\/tpodolak.com\/blog\/wp-content\/uploads\/2016\/02\/mocking-downstream-services-with-mountebank-part-one\/ConfigurationManager.png\" alt=\"ConfigurationManager\" width=\"437\" class=\"aligncenter size-full wp-image-620\" srcset=\"https:\/\/tpodolak.com\/blog\/wp-content\/uploads\/2016\/02\/mocking-downstream-services-with-mountebank-part-one\/ConfigurationManager.png 446w, https:\/\/tpodolak.com\/blog\/wp-content\/uploads\/2016\/02\/mocking-downstream-services-with-mountebank-part-one\/ConfigurationManager-150x55.png 150w, https:\/\/tpodolak.com\/blog\/wp-content\/uploads\/2016\/02\/mocking-downstream-services-with-mountebank-part-one\/ConfigurationManager-300x110.png 300w\" sizes=\"(max-width: 446px) 100vw, 446px\" \/><\/a><br \/>\nand follow the steps presented in the pictures below<br \/>\n<a href=\"\/\/tpodolak.com\/blog\/wp-content\/uploads\/2016\/02\/mocking-downstream-services-with-mountebank-part-one\/ConfigurationManager2.png\" rel=\"attachment wp-att-621\"><img decoding=\"async\" src=\"\/\/tpodolak.com\/blog\/wp-content\/uploads\/2016\/02\/mocking-downstream-services-with-mountebank-part-one\/ConfigurationManager2.png\" alt=\"ConfigurationManager2\" width=\"700\" class=\"aligncenter size-full wp-image-621\" srcset=\"https:\/\/tpodolak.com\/blog\/wp-content\/uploads\/2016\/02\/mocking-downstream-services-with-mountebank-part-one\/ConfigurationManager2.png 700w, https:\/\/tpodolak.com\/blog\/wp-content\/uploads\/2016\/02\/mocking-downstream-services-with-mountebank-part-one\/ConfigurationManager2-150x95.png 150w, https:\/\/tpodolak.com\/blog\/wp-content\/uploads\/2016\/02\/mocking-downstream-services-with-mountebank-part-one\/ConfigurationManager2-300x189.png 300w\" sizes=\"(max-width: 700px) 100vw, 700px\" \/><\/a><br \/>\n<a href=\"\/\/tpodolak.com\/blog\/wp-content\/uploads\/2016\/02\/mocking-downstream-services-with-mountebank-part-one\/ConfigurationManager3.png\" rel=\"attachment wp-att-622\"><img decoding=\"async\" src=\"\/\/tpodolak.com\/blog\/wp-content\/uploads\/2016\/02\/mocking-downstream-services-with-mountebank-part-one\/ConfigurationManager3.png\" alt=\"ConfigurationManager3\" width=\"437\" class=\"aligncenter size-full wp-image-622\" srcset=\"https:\/\/tpodolak.com\/blog\/wp-content\/uploads\/2016\/02\/mocking-downstream-services-with-mountebank-part-one\/ConfigurationManager3.png 437w, https:\/\/tpodolak.com\/blog\/wp-content\/uploads\/2016\/02\/mocking-downstream-services-with-mountebank-part-one\/ConfigurationManager3-150x84.png 150w, https:\/\/tpodolak.com\/blog\/wp-content\/uploads\/2016\/02\/mocking-downstream-services-with-mountebank-part-one\/ConfigurationManager3-300x169.png 300w\" sizes=\"(max-width: 437px) 100vw, 437px\" \/><\/a><\/p>\n<p>Now it is time to prepare our <i>app.config<\/i> for transformations. We can do it manually but for sake of simplicity I will use <i>SlowCheetah<\/i> extension. Go to <i>Tools->Extensions and Updates<\/i> and install<br \/>\n<a href=\"https:\/\/visualstudiogallery.msdn.microsoft.com\/69023d00-a4f9-4a34-a6cd-7e854ba318b5\">SlowCheetah &#8211; XML Transforms<\/a>. Once extension is installed you will see a <i>Add Transform<\/i> item in a config files&#8217; context menu.<br \/>\n<a href=\"\/\/tpodolak.com\/blog\/wp-content\/uploads\/2016\/02\/mocking-downstream-services-with-mountebank-part-one\/AddTransform.png\" rel=\"attachment wp-att-619\"><img decoding=\"async\" src=\"\/\/tpodolak.com\/blog\/wp-content\/uploads\/2016\/02\/mocking-downstream-services-with-mountebank-part-one\/AddTransform.png\" alt=\"AddTransform\" width=\"437\" class=\"aligncenter size-full wp-image-619\" srcset=\"https:\/\/tpodolak.com\/blog\/wp-content\/uploads\/2016\/02\/mocking-downstream-services-with-mountebank-part-one\/AddTransform.png 432w, https:\/\/tpodolak.com\/blog\/wp-content\/uploads\/2016\/02\/mocking-downstream-services-with-mountebank-part-one\/AddTransform-150x101.png 150w, https:\/\/tpodolak.com\/blog\/wp-content\/uploads\/2016\/02\/mocking-downstream-services-with-mountebank-part-one\/AddTransform-300x201.png 300w\" sizes=\"(max-width: 432px) 100vw, 432px\" \/><\/a><br \/>\nClicking <i>Add Transform<\/i> will create three files: <i>App.Debug.config<\/i>, <i>App.Release.config<\/i> and <i>App.Test.Integration.config<\/i>. What is more, some additional changes will be added to your <i>csproj<\/i> file, which will be responsible for applying transformations during a build process. These three additional files hold information about config transformations. The default <i>App.config<\/i> file looks like that<\/p>\n<pre lang=\"xml\">\r\n<?xml version=\"1.0\" encoding=\"utf-8\" ?>\r\n<configuration>\r\n  <appSettings file=\"\">\r\n    <add key=\"commonKey\" value=\"commonValue\"\/>\r\n  <\/appSettings>\r\n<\/configuration>\r\n<\/pre>\n<p>Nothing special in here but note the empty <i>file<\/i> attribute in <i>appSettings<\/i> node. The value of this attribute will be replaced with proper filename during transformation process. In order to do that let&#8217;s implement tramsforms for every of three config files we use<\/p>\n<p><b><i>App.Debug.config<\/i><\/b><\/p>\n<pre lang=\"xml\">\r\n<?xml version=\"1.0\" encoding=\"utf-8\" ?>\r\n<!-- For more information on using transformations \r\n     see the web.config examples at http:\/\/go.microsoft.com\/fwlink\/?LinkId=214134. -->\r\n<configuration xmlns:xdt=\"http:\/\/schemas.microsoft.com\/XML-Document-Transform\">\r\n  <appSettings file=\"app.settings.debug\" xdt:Transform=\"SetAttributes\">\r\n  <\/appSettings>\r\n<\/configuration>\r\n<\/pre>\n<p><b><i>App.Release.config<\/i><\/b><\/p>\n<pre lang=\"xml\">\r\n<?xml version=\"1.0\" encoding=\"utf-8\" ?>\r\n<!-- For more information on using transformations \r\n     see the web.config examples at http:\/\/go.microsoft.com\/fwlink\/?LinkId=214134. -->\r\n<configuration xmlns:xdt=\"http:\/\/schemas.microsoft.com\/XML-Document-Transform\">\r\n  <appSettings file=\"app.settings.release\" xdt:Transform=\"SetAttributes\">\r\n  <\/appSettings>\r\n<\/configuration>\r\n<\/pre>\n<p><b><i>App.Test.Integration.config<\/i><\/b><\/p>\n<pre lang=\"xml\">\r\n<?xml version=\"1.0\" encoding=\"utf-8\" ?>\r\n<!-- For more information on using transformations \r\n     see the web.config examples at http:\/\/go.microsoft.com\/fwlink\/?LinkId=214134. -->\r\n<configuration xmlns:xdt=\"http:\/\/schemas.microsoft.com\/XML-Document-Transform\">\r\n  <appSettings file=\"app.settings.tests.integration\" xdt:Transform=\"SetAttributes\">\r\n  <\/appSettings>\r\n<\/configuration>\r\n<\/pre>\n<p>As you can see I apply <i>SetAttributes<\/i> transform for <i>appSettings<\/i> node, which means that the transformation will replace <i>appSettings<\/i> node attributes from <i>app.config<\/i> file with  <i>appSettings<\/i> node attributes from transform file. You can preview results of transformation by clicking <i>Preview Transform<\/i> context menu option available for every of our transform files<br \/>\n<a href=\"\/\/tpodolak.com\/blog\/wp-content\/uploads\/2016\/02\/mocking-downstream-services-with-mountebank-part-one\/Preview.png\" rel=\"attachment wp-att-625\"><img decoding=\"async\" src=\"\/\/tpodolak.com\/blog\/wp-content\/uploads\/2016\/02\/mocking-downstream-services-with-mountebank-part-one\/Preview.png\" alt=\"Preview\" width=\"800\" class=\"aligncenter size-full wp-image-625\" srcset=\"https:\/\/tpodolak.com\/blog\/wp-content\/uploads\/2016\/02\/mocking-downstream-services-with-mountebank-part-one\/Preview.png 1321w, https:\/\/tpodolak.com\/blog\/wp-content\/uploads\/2016\/02\/mocking-downstream-services-with-mountebank-part-one\/Preview-150x29.png 150w, https:\/\/tpodolak.com\/blog\/wp-content\/uploads\/2016\/02\/mocking-downstream-services-with-mountebank-part-one\/Preview-300x57.png 300w, https:\/\/tpodolak.com\/blog\/wp-content\/uploads\/2016\/02\/mocking-downstream-services-with-mountebank-part-one\/Preview-1024x196.png 1024w\" sizes=\"(max-width: 1321px) 100vw, 1321px\" \/><\/a><br \/>\nAs you&#8217;ve probably already figured it out <i>app.settings.debug<\/i> and <i>app.settings.release<\/i> fileses contain real downstream endpoints and <i>app.settings.tests.integration<\/i> contains addresses of fake endpoints. Of course you have to create those files and copy them to output directory during the build (for instance by using <i>Copy to Output directory<\/i> option).<\/p>\n<h4>3.2. Creating fake downstreams with mountebank<\/h4>\n<p>Setting up fake downstream systems completely from scratch would be a very painful and time consuming process. Fortunately there are tools which can make this task easier. The tool I use is called <a href=\"http:\/\/www.mbtest.org\/\">mountebank<\/a> &#8211; you can easily install it via <i>npm<\/i><\/p>\n<pre lang=\"bash\">\r\nnpm install -g mountebank\r\n<\/pre>\n<p>Having <i>mountebank<\/i> on board it is time to configure it, so that it acts as fake <i>Pricer<\/i> service. It can be done in couple of ways but I will go with file based configuration. You can run the tool using following command<\/p>\n<pre lang=\"bash\">\r\nmb --configfile impostors.ejs --allowInjection\r\n<\/pre>\n<p><a href=\"\/\/tpodolak.com\/blog\/wp-content\/uploads\/2016\/02\/mocking-downstream-services-with-mountebank\/ImpostorsListening.png\" rel=\"attachment wp-att-642\"><img decoding=\"async\" src=\"\/\/tpodolak.com\/blog\/wp-content\/uploads\/2016\/02\/mocking-downstream-services-with-mountebank\/ImpostorsListening.png\" alt=\"ImpostorsListening\" width=\"700\"  class=\"aligncenter size-full wp-image-642\" srcset=\"https:\/\/tpodolak.com\/blog\/wp-content\/uploads\/2016\/02\/mocking-downstream-services-with-mountebank\/ImpostorsListening.png 764w, https:\/\/tpodolak.com\/blog\/wp-content\/uploads\/2016\/02\/mocking-downstream-services-with-mountebank\/ImpostorsListening-150x63.png 150w, https:\/\/tpodolak.com\/blog\/wp-content\/uploads\/2016\/02\/mocking-downstream-services-with-mountebank\/ImpostorsListening-300x126.png 300w\" sizes=\"(max-width: 764px) 100vw, 764px\" \/><\/a><br \/>\nWhere <i>impostors.ejs<\/i> is a configuration file with following structure<\/p>\n<pre lang=\"javascript\">\r\n{\r\n  \"imposters\": [\r\n    <% include pricer.json %>\r\n  ]\r\n}\r\n<\/pre>\n<p><i><% include pricer.json %><\/i> is <i><a href=\"http:\/\/www.embeddedjs.com\/\">EJS<\/a><\/i> syntax which (in this case) allows you to split configuration into multiple files. As you&#8217;ve probably already figured it out, <i>Pricer.json<\/i> contains the actual mock configuration for <i>Pricer<\/i> service. The initial mock object consists of couple of properties which setup the name, port and protocol for given mock. <\/p>\n<pre lang=\"javascript\">\r\n{\r\n  \"port\": 4545,\r\n  \"protocol\": \"http\",\r\n  \"name\": \"pricer stub\",\r\n  \"stubs\": []\r\n}\r\n<\/pre>\n<p>Note that we do not specify the address of mock but just a port. <i>Mountebank<\/i> by default runs on <i>http:\/\/localhost:2525<\/i> and mocks listen on <i>http:\/\/localhost:{port}<\/i>. The actual magic happens in <i>stubs<\/i> property.<br \/>\nHere is an example of stub\/mock for <i>GetTradingDates<\/i> method.<\/p>\n<pre lang=\"javascript\">\r\n{\r\n    \"responses\": [\r\n      {\r\n        \"is\": {\r\n          \"body\": {\r\n            \"MaturityDate\": \"2016-02-17\",\r\n            \"SettlementDate\": \"2012-02-23\"\r\n          }\r\n        }\r\n      }\r\n    ],\r\n    \"predicates\": [\r\n      {\r\n        \"equals\": {\r\n          \"path\": \"\/GetTradingDates\",\r\n          \"method\": \"GET\"\r\n        },\r\n      }\r\n    ]\r\n}\r\n<\/pre>\n<p>As you can see stub object consists of two properties<\/p>\n<ul>\n<li>responses<\/li>\n<li>predicates <\/li>\n<\/ul>\n<p><b><i>responses<\/i><\/b> property is an array of objects <i>mountebank<\/i> will be using to create a response. If you insert multiple items into array, they will be utilized using round robin algorithm. Note that you don&#8217;t have to create a full response (with all the headers etc.) just use &#8220;is&#8221; property which will fill the default values for you. More about that topic can be found <a href=\"http:\/\/www.mbtest.org\/docs\/api\/stubs\">here <\/a> but in most of the cases setting value for &#8220;body&#8221; property will be enough for you.<\/p>\n<p><b><i>predicates<\/i><\/b> property is an array of predicates which will be used during matching process. Predicate object can be quite complex, it supports lots of different matching techniques. In this case, for simple <i>GET<\/i> method I just use <i>equals<\/i> operator to match <i>HTTP<\/i> verb and <i>HTTP<\/i> method.<br \/>\nThe same technique can be used for stubbing <i>POST<\/i> methods. However, in this case, you can also perform matching against the body of the request. The one thing you have to remember is that <i>body<\/i> property is not an object but string. So in my case, if I want to make a stub for <i>GetPrice<\/i> which takes as params following request object <\/p>\n<pre lang=\"csharp\">\r\npublic class GetPriceRequest\r\n{\r\n    public bool IsAdvised { get; set; }\r\n}\r\n<\/pre>\n<p>I can write for instance this stub<\/p>\n<pre lang=\"javascript\">\r\n{\r\n    \"responses\": [\r\n      {\r\n        \"is\": {\r\n          \"body\": {\r\n            \"Id\": \"1\",\r\n            \"Strike\": \"1\"\r\n          }\r\n        }\r\n      }\r\n    ],\r\n    \"predicates\": [\r\n      {\r\n        \"equals\": {\r\n          \"path\": \"\/GetPrice\",\r\n          \"method\": \"POST\",\r\n          \"body\": \"{\\\"IsAdvised\\\":false}\"\r\n        }\r\n      }\r\n    ]\r\n}\r\n<\/pre>\n<p>Of course for more complex request it is pointless to write every possible combination of params. Fortunately you can create fallback\/default stub which will match everything<\/p>\n<pre lang=\"javascript\">\r\n{\r\n    \"responses\": [\r\n      {\r\n        \"is\": {\r\n          \"body\": {\r\n            \"Id\": \"default\",\r\n            \"Strike\": \"1\"\r\n          }\r\n        }\r\n      }\r\n    ],\r\n    \"predicates\": [\r\n      {\r\n        \"equals\": {\r\n          \"path\": \"\/GetPrice\",\r\n          \"method\": \"POST\"\r\n        }\r\n      }\r\n    ]\r\n}\r\n<\/pre>\n<p>If you put this at the very end of stubs array it will not interfere with other stubs.<br \/>\nThis is of course just a tip of the iceberg when it comes to predicate matching. Explanation of all possible matching options can be found <a href=\"http:\/\/www.mbtest.org\/docs\/api\/predicates\">here<\/a><\/p>\n<h3>4. Results<\/h3>\n<p>From now on running tests against <i>test.integration<\/i> compilation profile and having <i>mountebank<\/i> working in the background, our tests will be green.<br \/>\n<a href=\"\/\/tpodolak.com\/blog\/wp-content\/uploads\/2016\/02\/mocking-downstream-services-with-mountebank\/SuccessfulTests.png\" rel=\"attachment wp-att-643\"><img decoding=\"async\" src=\"\/\/tpodolak.com\/blog\/wp-content\/uploads\/2016\/02\/mocking-downstream-services-with-mountebank\/SuccessfulTests.png\" alt=\"SuccessfulTests\" width=\"700\"  class=\"aligncenter size-full wp-image-643\" srcset=\"https:\/\/tpodolak.com\/blog\/wp-content\/uploads\/2016\/02\/mocking-downstream-services-with-mountebank\/SuccessfulTests.png 981w, https:\/\/tpodolak.com\/blog\/wp-content\/uploads\/2016\/02\/mocking-downstream-services-with-mountebank\/SuccessfulTests-150x70.png 150w, https:\/\/tpodolak.com\/blog\/wp-content\/uploads\/2016\/02\/mocking-downstream-services-with-mountebank\/SuccessfulTests-300x141.png 300w\" sizes=\"(max-width: 981px) 100vw, 981px\" \/><\/a><br \/>\nSource code for this post can be found <a href=\"https:\/\/github.com\/tpodolak\/Blog\/tree\/master\/MockingDownstreamServicesWithMountebank\">here<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>1. Introduction I&#8217;m a part of a team which creates large enterprise platform for the banking sector. Due to the fact that we operate in the financial area, our application consumes a high amount of downstream services. One of the major problems we are facing at the moment is the inaccessibility of those services on [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[292,291],"tags":[294,293],"class_list":["post-614","post","type-post","status-publish","format-standard","hentry","category-mountebank","category-testing","tag-mountebank","tag-testing"],"_links":{"self":[{"href":"https:\/\/tpodolak.com\/blog\/wp-json\/wp\/v2\/posts\/614","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/tpodolak.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/tpodolak.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/tpodolak.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/tpodolak.com\/blog\/wp-json\/wp\/v2\/comments?post=614"}],"version-history":[{"count":62,"href":"https:\/\/tpodolak.com\/blog\/wp-json\/wp\/v2\/posts\/614\/revisions"}],"predecessor-version":[{"id":1074,"href":"https:\/\/tpodolak.com\/blog\/wp-json\/wp\/v2\/posts\/614\/revisions\/1074"}],"wp:attachment":[{"href":"https:\/\/tpodolak.com\/blog\/wp-json\/wp\/v2\/media?parent=614"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/tpodolak.com\/blog\/wp-json\/wp\/v2\/categories?post=614"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/tpodolak.com\/blog\/wp-json\/wp\/v2\/tags?post=614"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}