{"id":11325,"date":"2015-06-02T10:35:44","date_gmt":"2015-06-02T08:35:44","guid":{"rendered":"http:\/\/www.devapp.it\/wordpress\/?p=11325"},"modified":"2016-02-03T17:17:30","modified_gmt":"2016-02-03T16:17:30","slug":"come-creare-mock-api-per-le-nostre-applicazioni","status":"publish","type":"post","link":"https:\/\/www.devapp.it\/wordpress\/come-creare-mock-api-per-le-nostre-applicazioni\/","title":{"rendered":"Come creare mock API per le nostre applicazioni"},"content":{"rendered":"<p>La maggior parte delle applicazioni mobile hanno in qualche modo a che fare con delle API esterne. In alcuni casi proprio le API costituiscono il cuore dell&#8217;applicazione: recuperare dei dati in json, visualizzarli e processarli in qualche modo&#8230; non \u00e8 forse questo lo scopo della maggior parte delle app?<\/p>\n<p>Anche se tutti abbiamo ormai imparato a interagire con le API usando librerie come AFNetworking, o pi\u00f9 semplicemente tramite alcune NSURLRequest,\u00a0il networking resta una parte molto fragile dell&#8217;architettura, se non altro perch\u00e9 coinvolge due parti separate: la nostra app e il backend che fornisce i dati. Pu\u00f2 essere quindi interessante cercare di capire come riuscire a testare efficacemente questa parte del programma e come riuscire a lavorare serenamente anche quando il server non \u00e8 raggiungibile o le API non sono ancora state sviluppate.<\/p>\n<h3>Unit test e http calls<\/h3>\n<p>Provando a ragionare sul primo punto, l&#8217;argomento \u00e8 piuttosto spinoso e le battaglie in rete sono pi\u00f9 aspre delle battaglie di religione in medio oriente. L&#8217;unico punto che vede tutti d&#8217;accordo \u00e8 *mai* interagire con la rete durante i test. La ragione \u00e8 semplice: abbiamo definito un contratto con il backend sulla struttura del json , http status codes etc e quello che vogliamo testare \u00e8 che la nostra app si comporti correttamente quando il contratto \u00e8 rispettato. Interagire direttamente con la rete significa testare contemporaneamente due parti del sistema, testare la nostra app e testare che il backend stia rispettando il contratto. Testare due componenti del sistema \u00e8 chiamato &#8220;<strong>integration test<\/strong>&#8221; ed \u00e8 ben diverso dai test che scriviamo all&#8217;interno della nostra app, quindi il concetto \u00e8 chiaro:<\/p>\n<p><strong>mai utilizzare la rete durante i test<\/strong> \ud83d\ude42<\/p>\n<p>Effettuare i test, senza l&#8217;utilizzo della rete \u00e8 possibile e le tecniche posso essere le pi\u00f9 diverse, io per esempio preferisco lasciare pochissima (praticamente nessuna) logica all&#8217;interno della classe che si occupa del networking spostando tutto in classi esterne, in questo modo la classe che effettua le chiamate http non \u00e8 altro che un insieme di chiamate a NSUrlRequest \/ AFNetworking e nulla pi\u00f9, e pu\u00f2 essere tranquillamente sostituita durante i test con una classe che recupera i json dal filesystem piuttosto che dalla rete.<\/p>\n<p>Questo approccio ha per me un grande vantaggio, infatti poich\u00e9 in azienda viene dato molto peso ai test manuali, abbiamo un particolare target che utilizza questa mock class, e tramite settings il tester pu\u00f2 in autonomia modificare alcuni parametri e\u00a0verificare il comportamento dell&#8217;app in caso di assenza di rete, limitata connettivit\u00e0 o generici errori di rete (http 500) tutto questo prima ancora che il backend sia effettivamente pronto.<\/p>\n<p>Se invece non avete voglia di sbattervi nel creare classi separate solo per i test, potete utilizzare una libreria che permetta di mock-are (sorry per il termine) le richieste http, come per esempio <strong>Nocilla<\/strong> (<a href=\"https:\/\/github.com\/luisobo\/Nocilla\" target=\"_blank\">https:\/\/github.com\/luisobo\/Nocilla<\/a>) oppure <strong>WebMock<\/strong> (<a href=\"https:\/\/github.com\/bblimke\/webmock\" target=\"_blank\">https:\/\/github.com\/bblimke\/webmock<\/a>) o ancora <strong>OHHTTPStubs<\/strong> (<a href=\"https:\/\/github.com\/AliSoftware\/OHHTTPStubs\" target=\"_blank\">https:\/\/github.com\/AliSoftware\/OHHTTPStubs<\/a>).<\/p>\n<p>Il vantaggio dell&#8217;utilizzare una libreria come quelle proposte \u00e8 che la libreria opera ad un livello molto basso, per cui una volta correttamente &#8220;abilitata&#8221;, tutto il resto dell&#8217;applicazione pu\u00f2 restare immutato. Le chiamate http verranno semplicemente intercettate e le specifiche &#8220;finte&#8221; risposte verranno portate al livello superiore.<\/p>\n<h3>Mock api<\/h3>\n<p>Quando lo sviluppo dell&#8217;applicazione iOS inizia contemporaneamente (se non prima) dello sviluppo del backend bisogna in qualche modo invenarsi un sistema per <strong>simulare le API<\/strong>. Qualcuno potrebbe dire: &#8220;ma se abbiamo usato un OHHTTPStubs abbiamo gi\u00e0 le nostre mock api&#8221; e in effetti \u00e8 parzialmente vero.. ma \u00e8 anche vero che il vostro compagno di banco sta sviluppando la versione android, e magari volete avere anche un po&#8217; di dati in pi\u00f9 per provare sul campo l&#8217;applicazione.. quindi vediamo quali sono le possibilit\u00e0 per creare una API finta.<\/p>\n<p>La decisione principale \u00e8 se voler realizzare qualcosa con le nostre manine oppure usare un tool gi\u00e0 pronto all&#8217;uso. Inutile dire che il primo approccio \u00e8 anche il pi\u00f9 soddisfacente e il pi\u00f9 versatile, quindi soprattutto se vi piace sporcarvi le mani.. go ahead! Il mio personale approccio in genere passa attraverso una semplice applicazione ruby deployata su heroku. \u00c8 sorprendente notare come possa essere semplice generare un mock server con ruby e una libreria come Sinatra o Grape.<\/p>\n<p>Giusto per fare un esempio\u00a0 questo \u00e8 tutto il codice necessario per restituire un json quando interrogate:<\/p>\n<pre class=\"\">example.com\/v1\/countries<\/pre>\n<pre class=\"theme:dark-terminal lang:ruby decode:true\">get '\/v1\/countries' do\r\n  content_type :json\r\n  {data: [country_1(), country_2()]}.to_json\r\nend\r\n<\/pre>\n<p>Registratevi su Heroku se non l&#8217;avete mai fatto,\u00a0prendete un template di applicazione Sinatra (per esempio questo <a href=\"https:\/\/github.com\/sinatra\/heroku-sinatra-app\" target=\"_blank\">https:\/\/github.com\/sinatra\/heroku-sinatra-app<\/a>) e in 10 minuti avrete le vostre mock api.<\/p>\n<p><strong>Benefits<\/strong>: il piacere di aver fatto tutto da soli e la possibilit\u00e0 di avere anche quel pizzico di logica in pi\u00f9 all&#8217;interno delle API che non guasta mai. Per esempio alcune API restituiscono sempre la data corrente, cosa impossibile con altri servizi di mock.<\/p>\n<p><strong>Contro:<\/strong> Se dite in giro che avete deployato un&#8217;applicazione per fare da mock server vi prenderanno per pazzo perch\u00e9 sembra un lavoro enorme e complicato, mentre invece richiede 10 minuti \ud83d\ude42<\/p>\n<p>Cosa usare invece se non volete sporcarvi le mani? In questo caso mi sento di suggerire due prodotti diversi, il primo \u00e8 <strong>mockbin<\/strong> (<a href=\"http:\/\/mockbin.org\/\" target=\"_blank\">http:\/\/mockbin.org\/<\/a>) realizzato dagli stessi ragazzi italiani di mashape, free e open source, ha diverse funzionalit\u00e0 avanzate e se state cercando una soluzione facile e veloce per mockare una API \u00e8 assolutamente perfetto. Cosa volete di pi\u00f9? \ud83d\ude42<\/p>\n<p>Il secondo tool \u00e8 invece parzialmente a pagamento e si chiama <strong>apiary<\/strong> (<a href=\"http:\/\/apiary.io\" target=\"_blank\">http:\/\/apiary.io<\/a>). Questo tool ha uno scopo molto pi\u00f9 ampio, ed \u00e8 anche difficile da descrivere \ud83d\ude1b\u00a0In pratica basta scrivere la documentazione in un formato simil-markdown, aggiungendo anche esempi di risposta, e apiary si preoccupa di generare la documentazione, le mock api, generare snippet di codice per interagire con quella API e decine di altre cose \ud83d\ude42<\/p>\n<p>Non vi resta che provare e lasciare i vostri commenti sotto l&#8217;articolo!<\/p>\n<p>Alla prossima!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>La maggior parte delle applicazioni mobile hanno in qualche modo a che fare con delle API esterne&#8230;.<\/p>\n","protected":false},"author":53,"featured_media":11341,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[8],"tags":[1242,1511,1512,1513,867],"class_list":["post-11325","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-guide-varie","tag-api","tag-integration-test","tag-mock-api","tag-simulare-le-api","tag-unit-test"],"acf":[],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/posts\/11325","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/users\/53"}],"replies":[{"embeddable":true,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/comments?post=11325"}],"version-history":[{"count":12,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/posts\/11325\/revisions"}],"predecessor-version":[{"id":11727,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/posts\/11325\/revisions\/11727"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/media\/11341"}],"wp:attachment":[{"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/media?parent=11325"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/categories?post=11325"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/tags?post=11325"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}