{"id":12508,"date":"2017-05-03T11:04:28","date_gmt":"2017-05-03T10:04:28","guid":{"rendered":"http:\/\/blog.intercom.com\/?p=12508"},"modified":"2020-07-30T12:57:58","modified_gmt":"2020-07-30T11:57:58","slug":"building-better-mock-servers-mobile-speakeasy","status":"publish","type":"post","link":"https:\/\/www.intercom.com\/blog\/building-better-mock-servers-mobile-speakeasy\/","title":{"rendered":"Building better mock servers for mobile with Speakeasy"},"content":{"rendered":"<p class=\"opening_paragraph\">If you have a mobile app which communicates with a server through HTTP, then you (hopefully) have tests which ensure this communication works as expected.<\/p>\n<p>This usually involves providing canned responses in your tests, and doing this separately for iOS and Android. Pretty annoying, right? You\u2019re effectively duplicating work across multiple platforms, and the static nature of the responses make it difficult to test requests that cause data to be updated in the backend. Thankfully, there\u2019s a better way. At Intercom we\u2019ve improved on this by recreating our server logic in Go and embedding it into our iOS and Android apps.<\/p>\n<h2 id=\"the-old-way\">The old way ?<\/h2>\n<p>Previously we had two solutions for providing these server responses.<\/p>\n<p><strong>Android<\/strong>: We had a mock HTTP client return static JSON which was defined in our test code. This suffered from the typical problem where backend data updates were hard to test. A test which required four new messages to be added to a conversation required five canned responses.<\/p>\n<p><strong>iOS<\/strong>: We had a Node.js server which emulated our server logic, and we ran it locally on the same machine as the iOS simulator we were testing on. This allowed us to test the updating of data easily, but it meant that a testing environment required the ability to run external programs. This prevented us from using remote testing services like Firebase Test Lab and Xamarin Test Cloud.<\/p>\n<p>We had almost resigned ourselves to using the Node.js server on Android too, but we decided to investigate other options and discovered <a href=\"https:\/\/github.com\/golang\/mobile\">gomobile<\/a>, an experimental Go tool which makes it easy to use Go code inside Android and iOS apps. We decided to try using this to make our apps talk to a Go web server running on the same device.<\/p>\n<h2 id=\"the-new-way\">The new way ?<\/h2>\n<p>The first part of this was implementing our server logic in Go. This was actually much easier than a real backend implementation as we didn&#8217;t need to worry about scaling, persistence, etc. It just needed to return the same HTTP responses as our API did in production. We used <a href=\"https:\/\/github.com\/gorilla\/mux\">Mux<\/a> to route the requests and relied on Go&#8217;s built-in JSON support to create and marshal our model objects. The common Speakeasy package defines a server that can take an Engine which decides how requests are handled.<\/p>\n<p><code class=\"prettyprint\" style=\"word-wrap: break-word;\"><br \/>\nfunc (server *Server) Start() {<br \/>\nserver.Engine.Setup(server)<br \/>\nlog.Fatal(http.ListenAndServe(\":3000\", server.Router))<br \/>\n}<br \/>\nfunc (engine *SampleEngine) Setup(server *speakeasy.Server) {<br \/>\nhandler := engine.WrapHandler(engine.channelsResponse)<br \/>\nserver.Router.HandleFunc(\"\/channels\", handler).Methods(\"GET\")<br \/>\n}<br \/>\nfunc (engine *SampleEngine) channelsResponse(w http.ResponseWriter, r *http.Request) {<br \/>\njson.NewEncoder(w).Encode(ChannelsResponse{engine.AppState.ChannelNameList()})<br \/>\n}<br \/>\n<\/code><\/p>\n<p>The second part of this is embedding the server code in your app. You can do this using the Speakeasy tool which will generate an AAR file for Android and a framework for iOS. In our apps we distribute these through internal Maven and Cocoapods repos for easy integration and versioning. After including these in your app you can access your Go code through generated JNI methods in Android and C\/Objective-C methods in iOS.<\/p>\n<p><code class=\"prettyprint\" style=\"word-wrap: break-word;\"><br \/>\n\/\/ SpeakeasyApplication.java<br \/>\nserverEngine = Backend.newEngine();<br \/>\nfinal Server speakeasyServer = Speakeasy.newServer(serverEngine);<br \/>\nThread serverThread = new Thread(new Runnable() {<br \/>\n@Override public void run() {<br \/>\nspeakeasyServer.start();<br \/>\n}<br \/>\n}, \"SpeakeasyServer\");<br \/>\nserverThread.start();<br \/>\n<\/code><\/p>\n<h2 id=\"how-this-has-helped-us\">How this has helped us<\/h2>\n<p>We&#8217;ve seen a lot of benefits to using this:<\/p>\n<ul>\n<li>Any change to the mock server logic only needs to be done once between Android and iOS, cutting the workload in half! The less effort a test change makes, the more likely you are to update your tests and write new ones.<\/li>\n<li>As well as using this for our HTTP API, we\u2019ve also been able to use this for our WebSockets-based real-time API too. This allows us to easily simulate events like seen states or typing indicators for a message.<\/li>\n<li>The app is completely self-contained, so your tests can run on any device or emulator, with or without an internet connection. You can even add buttons to your debug build which trigger push events from the server.<\/li>\n<li>Building a sandbox version of your app is incredibly easy. You can add buttons to your app to send data from the server to the client (e.g. over WebSockets), making testing real-time communication much simpler.<\/li>\n<li>When a developer working on one platform makes changes to the server logic, it makes it clear to developers working on other platforms that their tests need updating. If they don&#8217;t, then there&#8217;s a gap in test coverage<\/li>\n<\/ul>\n<p>We&#8217;re working on ways to check that the behaviour of your mock implementation stays completely aligned with the behaviour of the real server. If they behave differently then your tests won\u2019t be very useful ?<\/p>\n<h2 id=\"how-to-use-it\">How to use it<\/h2>\n<p><a href=\"https:\/\/github.com\/intercom\/speakeasy\">Speakeasy is available on Github<\/a>. In the repo you\u2019ll find a sample Android app and setup scripts. Using it in your app is simple:<\/p>\n<ul>\n<li>Run <code class=\"prettyprint\" style=\"word-wrap: break-word;\">go get github.com\/intercom\/speakeasy\/cmd\/speakeasy<\/code><\/li>\n<li>Run <code class=\"prettyprint\" style=\"word-wrap: break-word;\">$GOPATH\/src\/github.com\/intercom\/speakeasy\/setup.sh<\/code> to set up all the dependencies needed<\/li>\n<li>Create your own Go package with a type that implements the <code class=\"prettyprint\" style=\"word-wrap: break-word;\">speakeasy.Engine<\/code> interface<\/li>\n<li>Run <code class=\"prettyprint\" style=\"word-wrap: break-word;\">speakeasy build {your package path}<\/code><\/li>\n<li>Add the server as a dependency in your app<\/li>\n<li>Create a new engine object in your app, create a server with it and start the server on a background thread<\/li>\n<\/ul>\n<p>We\u2019ve found Speakeasy really useful over the past months, and think you will too. If you\u2019ve any questions, drop me a mail, or come ask me a question at the <a href=\"https:\/\/www.meetup.com\/Dublin-Go-Meetup\/events\/239475650\/\">Dublin Go Meetup<\/a> at the Intercom office on May 4th.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>If you have a mobile app which communicates with a server through HTTP, then you (hopefully) have tests which ensure this communication works as expected. This usually involves providing canned responses in your tests, and doing&hellip;<\/p>\n","protected":false},"author":240,"featured_media":12509,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"category":[4],"tags":[335,201],"coauthors":[516],"class_list":["post-12508","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-news","tag-engineering","tag-mobile"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v27.3 (Yoast SEO v27.3) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Building better mock servers for mobile with Speakeasy<\/title>\n<meta name=\"description\" content=\"How we use the Go programming language to build better mock servers for our iOS and Android apps.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.intercom.com\/blog\/building-better-mock-servers-mobile-speakeasy\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Building better mock servers for mobile with Speakeasy\" \/>\n<meta property=\"og:description\" content=\"How we use the Go programming language to build better mock servers for our iOS and Android apps.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.intercom.com\/blog\/building-better-mock-servers-mobile-speakeasy\/\" \/>\n<meta property=\"og:site_name\" content=\"The Intercom Blog\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/intercominc\" \/>\n<meta property=\"article:published_time\" content=\"2017-05-03T10:04:28+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2020-07-30T11:57:58+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.intercom.com\/blog\/wp-content\/uploads\/2017\/05\/Building-better-mock-servers-for-mobile-with-Speakeasy.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1968\" \/>\n\t<meta property=\"og:image:height\" content=\"932\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Conor O&#039;Donnell\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@ronocod\" \/>\n<meta name=\"twitter:site\" content=\"@intercom\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Conor O&#039;Donnell\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"5 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/building-better-mock-servers-mobile-speakeasy\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/building-better-mock-servers-mobile-speakeasy\\\/\"},\"author\":{\"name\":\"Conor O'Donnell\",\"@id\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/#\\\/schema\\\/person\\\/c1ba54b6251c13af6d47c9c374bf8147\"},\"headline\":\"Building better mock servers for mobile with Speakeasy\",\"datePublished\":\"2017-05-03T10:04:28+00:00\",\"dateModified\":\"2020-07-30T11:57:58+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/building-better-mock-servers-mobile-speakeasy\\\/\"},\"wordCount\":838,\"publisher\":{\"@id\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/building-better-mock-servers-mobile-speakeasy\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/wp-content\\\/uploads\\\/2017\\\/05\\\/Building-better-mock-servers-for-mobile-with-Speakeasy.jpg\",\"keywords\":[\"Engineering\",\"mobile\"],\"articleSection\":[\"News &amp; Updates\"],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/building-better-mock-servers-mobile-speakeasy\\\/\",\"url\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/building-better-mock-servers-mobile-speakeasy\\\/\",\"name\":\"Building better mock servers for mobile with Speakeasy\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/building-better-mock-servers-mobile-speakeasy\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/building-better-mock-servers-mobile-speakeasy\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/wp-content\\\/uploads\\\/2017\\\/05\\\/Building-better-mock-servers-for-mobile-with-Speakeasy.jpg\",\"datePublished\":\"2017-05-03T10:04:28+00:00\",\"dateModified\":\"2020-07-30T11:57:58+00:00\",\"description\":\"How we use the Go programming language to build better mock servers for our iOS and Android apps.\",\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.intercom.com\\\/blog\\\/building-better-mock-servers-mobile-speakeasy\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/building-better-mock-servers-mobile-speakeasy\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/wp-content\\\/uploads\\\/2017\\\/05\\\/Building-better-mock-servers-for-mobile-with-Speakeasy.jpg\",\"contentUrl\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/wp-content\\\/uploads\\\/2017\\\/05\\\/Building-better-mock-servers-for-mobile-with-Speakeasy.jpg\",\"width\":1968,\"height\":932,\"caption\":\"Go Code better mock servers with go code\"},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/\",\"name\":\"The Intercom Blog\",\"description\":\"Articles and Podcasts on Customer Service, AI and Automation, Product, and more\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/#organization\",\"name\":\"The Intercom Blog\",\"url\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/wp-content\\\/uploads\\\/2019\\\/08\\\/Intercom-logo-sq-black-trans.png\",\"contentUrl\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/wp-content\\\/uploads\\\/2019\\\/08\\\/Intercom-logo-sq-black-trans.png\",\"width\":1000,\"height\":1000,\"caption\":\"The Intercom Blog\"},\"image\":{\"@id\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/intercominc\",\"https:\\\/\\\/x.com\\\/intercom\",\"https:\\\/\\\/www.instagram.com\\\/intercom\\\/\",\"https:\\\/\\\/www.linkedin.com\\\/company\\\/2491343\",\"https:\\\/\\\/www.pinterest.ie\\\/intercom\\\/\",\"https:\\\/\\\/www.youtube.com\\\/channel\\\/UCJG0MvLP03kyzzAkD-w98aQ\",\"https:\\\/\\\/en.wikipedia.org\\\/wiki\\\/Intercom_(company)\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/#\\\/schema\\\/person\\\/c1ba54b6251c13af6d47c9c374bf8147\",\"name\":\"Conor O'Donnell\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/9874840e0346e426ce22942284499001f1a5f7d1ecd472f17bf3a6439b70543e?s=96&d=mm&r=pgcea42d819505d168bc906b2e5fecaa2a\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/9874840e0346e426ce22942284499001f1a5f7d1ecd472f17bf3a6439b70543e?s=96&d=mm&r=pg\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/9874840e0346e426ce22942284499001f1a5f7d1ecd472f17bf3a6439b70543e?s=96&d=mm&r=pg\",\"caption\":\"Conor O'Donnell\"},\"sameAs\":[\"https:\\\/\\\/x.com\\\/ronocod\"],\"url\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/author\\\/ronocod\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Building better mock servers for mobile with Speakeasy","description":"How we use the Go programming language to build better mock servers for our iOS and Android apps.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.intercom.com\/blog\/building-better-mock-servers-mobile-speakeasy\/","og_locale":"en_US","og_type":"article","og_title":"Building better mock servers for mobile with Speakeasy","og_description":"How we use the Go programming language to build better mock servers for our iOS and Android apps.","og_url":"https:\/\/www.intercom.com\/blog\/building-better-mock-servers-mobile-speakeasy\/","og_site_name":"The Intercom Blog","article_publisher":"https:\/\/www.facebook.com\/intercominc","article_published_time":"2017-05-03T10:04:28+00:00","article_modified_time":"2020-07-30T11:57:58+00:00","og_image":[{"width":1968,"height":932,"url":"https:\/\/www.intercom.com\/blog\/wp-content\/uploads\/2017\/05\/Building-better-mock-servers-for-mobile-with-Speakeasy.jpg","type":"image\/jpeg"}],"author":"Conor O'Donnell","twitter_card":"summary_large_image","twitter_creator":"@ronocod","twitter_site":"@intercom","twitter_misc":{"Written by":"Conor O'Donnell","Est. reading time":"5 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.intercom.com\/blog\/building-better-mock-servers-mobile-speakeasy\/#article","isPartOf":{"@id":"https:\/\/www.intercom.com\/blog\/building-better-mock-servers-mobile-speakeasy\/"},"author":{"name":"Conor O'Donnell","@id":"https:\/\/www.intercom.com\/blog\/#\/schema\/person\/c1ba54b6251c13af6d47c9c374bf8147"},"headline":"Building better mock servers for mobile with Speakeasy","datePublished":"2017-05-03T10:04:28+00:00","dateModified":"2020-07-30T11:57:58+00:00","mainEntityOfPage":{"@id":"https:\/\/www.intercom.com\/blog\/building-better-mock-servers-mobile-speakeasy\/"},"wordCount":838,"publisher":{"@id":"https:\/\/www.intercom.com\/blog\/#organization"},"image":{"@id":"https:\/\/www.intercom.com\/blog\/building-better-mock-servers-mobile-speakeasy\/#primaryimage"},"thumbnailUrl":"https:\/\/www.intercom.com\/blog\/wp-content\/uploads\/2017\/05\/Building-better-mock-servers-for-mobile-with-Speakeasy.jpg","keywords":["Engineering","mobile"],"articleSection":["News &amp; Updates"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/www.intercom.com\/blog\/building-better-mock-servers-mobile-speakeasy\/","url":"https:\/\/www.intercom.com\/blog\/building-better-mock-servers-mobile-speakeasy\/","name":"Building better mock servers for mobile with Speakeasy","isPartOf":{"@id":"https:\/\/www.intercom.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.intercom.com\/blog\/building-better-mock-servers-mobile-speakeasy\/#primaryimage"},"image":{"@id":"https:\/\/www.intercom.com\/blog\/building-better-mock-servers-mobile-speakeasy\/#primaryimage"},"thumbnailUrl":"https:\/\/www.intercom.com\/blog\/wp-content\/uploads\/2017\/05\/Building-better-mock-servers-for-mobile-with-Speakeasy.jpg","datePublished":"2017-05-03T10:04:28+00:00","dateModified":"2020-07-30T11:57:58+00:00","description":"How we use the Go programming language to build better mock servers for our iOS and Android apps.","inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.intercom.com\/blog\/building-better-mock-servers-mobile-speakeasy\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.intercom.com\/blog\/building-better-mock-servers-mobile-speakeasy\/#primaryimage","url":"https:\/\/www.intercom.com\/blog\/wp-content\/uploads\/2017\/05\/Building-better-mock-servers-for-mobile-with-Speakeasy.jpg","contentUrl":"https:\/\/www.intercom.com\/blog\/wp-content\/uploads\/2017\/05\/Building-better-mock-servers-for-mobile-with-Speakeasy.jpg","width":1968,"height":932,"caption":"Go Code better mock servers with go code"},{"@type":"WebSite","@id":"https:\/\/www.intercom.com\/blog\/#website","url":"https:\/\/www.intercom.com\/blog\/","name":"The Intercom Blog","description":"Articles and Podcasts on Customer Service, AI and Automation, Product, and more","publisher":{"@id":"https:\/\/www.intercom.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.intercom.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.intercom.com\/blog\/#organization","name":"The Intercom Blog","url":"https:\/\/www.intercom.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.intercom.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/www.intercom.com\/blog\/wp-content\/uploads\/2019\/08\/Intercom-logo-sq-black-trans.png","contentUrl":"https:\/\/www.intercom.com\/blog\/wp-content\/uploads\/2019\/08\/Intercom-logo-sq-black-trans.png","width":1000,"height":1000,"caption":"The Intercom Blog"},"image":{"@id":"https:\/\/www.intercom.com\/blog\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/intercominc","https:\/\/x.com\/intercom","https:\/\/www.instagram.com\/intercom\/","https:\/\/www.linkedin.com\/company\/2491343","https:\/\/www.pinterest.ie\/intercom\/","https:\/\/www.youtube.com\/channel\/UCJG0MvLP03kyzzAkD-w98aQ","https:\/\/en.wikipedia.org\/wiki\/Intercom_(company)"]},{"@type":"Person","@id":"https:\/\/www.intercom.com\/blog\/#\/schema\/person\/c1ba54b6251c13af6d47c9c374bf8147","name":"Conor O'Donnell","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/9874840e0346e426ce22942284499001f1a5f7d1ecd472f17bf3a6439b70543e?s=96&d=mm&r=pgcea42d819505d168bc906b2e5fecaa2a","url":"https:\/\/secure.gravatar.com\/avatar\/9874840e0346e426ce22942284499001f1a5f7d1ecd472f17bf3a6439b70543e?s=96&d=mm&r=pg","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/9874840e0346e426ce22942284499001f1a5f7d1ecd472f17bf3a6439b70543e?s=96&d=mm&r=pg","caption":"Conor O'Donnell"},"sameAs":["https:\/\/x.com\/ronocod"],"url":"https:\/\/www.intercom.com\/blog\/author\/ronocod\/"}]}},"jetpack_featured_media_url":"https:\/\/www.intercom.com\/blog\/wp-content\/uploads\/2017\/05\/Building-better-mock-servers-for-mobile-with-Speakeasy.jpg","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.intercom.com\/blog\/wp-json\/wp\/v2\/posts\/12508","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.intercom.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.intercom.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.intercom.com\/blog\/wp-json\/wp\/v2\/users\/240"}],"replies":[{"embeddable":true,"href":"https:\/\/www.intercom.com\/blog\/wp-json\/wp\/v2\/comments?post=12508"}],"version-history":[{"count":0,"href":"https:\/\/www.intercom.com\/blog\/wp-json\/wp\/v2\/posts\/12508\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.intercom.com\/blog\/wp-json\/wp\/v2\/media\/12509"}],"wp:attachment":[{"href":"https:\/\/www.intercom.com\/blog\/wp-json\/wp\/v2\/media?parent=12508"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.intercom.com\/blog\/wp-json\/wp\/v2\/category?post=12508"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.intercom.com\/blog\/wp-json\/wp\/v2\/tags?post=12508"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.intercom.com\/blog\/wp-json\/wp\/v2\/coauthors?post=12508"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}