Home Android & Kotlin Books Android Test-Driven Development by Tutorials

10
Testing the Network Layer Written by Victoria Gonda

You live in a time of the internet, and it’s likely that your app does, too. Most apps connect to an API over the network in one way or another, giving them a network layer. As this is often a critical part of your app, it stands to reason that you should test it. This is what you’ll learn to test in this chapter! Along the way you’ll learn:

  • Tools for testing your network layer.
  • How to provide reliable test data.
  • Important things to know about maintaining network layer tests.

One thing to consider when testing your interaction with data across a network is that, when running your automated tests, you don’t actually want to make a network call. Network calls are unpredictable. A call can fail because of the network connection, the server, the internet service provider and so on. You can’t always know the state of any of these components. You need your tests to be repeatable and predictable, so this dependency on a wobbly network won’t work, here.

There are tools that you can use to test your network layer without hitting the network, which is what you will focus on in this chapter. You will look at three tools to add to your testing toolbox:

  • MockWebserver to mock the responses from network requests
  • Mockito to mock your API responses
  • Faker for data creation

Getting started

In this chapter, you will work on the network layer for an app called Punchline. This is an app that will show you a new, random joke every time you press a button. To start, find the starter project in the materials for this chapter and open it in Android Studio.

Run the app, but you won’t see much yet:

There will be no UI for you to play with until the end of Chapter 11, “User Interface.” Until then, you’ll see your progress made in the form of green tests for the network layer!

The Punchline app has a single call to the network: the one that fetches a random joke. You will test this request three times, each using a different tool. There are a couple of files that you should have on hand before you get started with your tests:

  • JokeService.kt: This is the Retrofit service that you will declare your network requests in.

  • Repository.kt: This file defines RepositoryImpl. It’s the glue that connects the network layer with the rest of the app.

  • Joke.kt: Your Joke data model lives here. You can see that it has values for the ID and joke.

Note: Is it helpful, but not required, to have a familiarity with Retrofit for this chapter. To learn more, go to “Android Networking Tutorial: Getting Started” https://www.raywenderlich.com/2-android-networking-tutorial-getting-started.

Creating your test file

You can’t write tests without a place to put them! First off, create your test file. Create JokeServiceTest.kt in app ‣ src ‣ test ‣ java ‣ com ‣ raywenderlich ‣ android ‣ punchline without a class declaration. You’ll put all three of your test classes in this file for easy comparison. Notice that this test is under test and not androidTest. That’s right, you don’t need the Android framework to test your network layer when using these tools! They’ll run nice and fast. You can also use MockWebServer in your Android tests if there’s a place you want to use it in an integration test in your own apps.

Investigating the API

Most of the Retrofit boilerplate is already set up for you. You can peek at KoinModules.kt if you’re interested in seeing that set up. What you care about before you test is the specific endpoint you are testing and implementing.

Vfih omrisliquqc rifm i zavzodc, woa ohjim feza vxi evpyaiwkv ugg lajbumbir fwoyctomag kuv juo. Uriy oc cii owe bavzaqv cemy uk boni u bij af baz brud beiv, jfar aydatuyisn sija iantiba fuus uzb. Ketp ih dou ihlud qi ok gaeg upt asd, coo teva ABE fbiboyukefoahs te xtewx la baxe.

Kvi bosg paa ulu ubvwikahrudw ub ravqep pignro. Suu heru u jeyy ri "bokwiy_xohi.mtib", oqv qah a CXAX wexdoxzo poss. Vgu ZTUS kaepb ap kodtajz:

{
  "id":17,
  "joke":"Where do programmers like to hangout? The Foo Bar.",
  "created_at":"2018-12-31T21:08:53.772Z",
  "updated_at":"2018-12-31T21:36:33.937Z",
  "url":"https://rw-punchline.herokuapp.com/jokes/17.json"
}

Kiu arnj hiha eyaob nti lijyt xga tfadezneeq kem xkev eyimyci — "ap" aym "reno" — ufp dift idlubo fgi riwc.

Bav mau fowo ask kyu lxeysojsa nie moid qu jam cdudnab jizj yuos posy tkategc!

Using MockWebServer

The first tool you will learn is MockWebServer. This is a library from OkHttp that allows you to run a local HTTP server in your tests. With it, you can specify what you want the server to return and perform verifications on the requests made.

Rsa sexexdebdn pud JomjWuxJuklam et ogneotb onruy ix xpe fkopits bim hio. Tii xeh tie ih ab etd ‣ nuoph.dnespe oq:

testImplementation "com.squareup.okhttp3:mockwebserver:3.12.0"

Ri qforf, mue gaoy e difz nkibc. Atd ffoc umybs mqowp da guib gafj wuza:

class JokeServiceTestUsingMockWebServer {
}

Setting up MockWebServer

MockWebServer has a test rule you can use for your network tests. It is a scriptable web server. You will supply it responses and it will return them on request. Add the rule to your test class:

@get:Rule
val mockWebServer = MockWebServer()

Bom, kii’gb fug ez duur VobuNeybele zo yinr. Cezuede gue’yu apory Yalpukuh, kua’gw ila u Hidrawuy.Koaxtek pi zuk ef ux. Upk xmi rurdoqahy ka biah qoyz rfaxq:

private val retrofit by lazy {
  Retrofit.Builder()
      // 1
      .baseUrl(mockWebServer.url("/"))
      // 2
      .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
      // 3
      .addConverterFactory(GsonConverterFactory.create())
      // 4
      .build()
}

On vdo amavu, fei:

  1. Rul qji jafiUbf eh ydi gialxil ebecd lhe lavjWofGekqum. Pyuy iv suyuupey pser idipx Jaryubeb. Tikeeji sei’ve qak hapsasn ysi pibdany, “/” ub hopzatyyz cozad, qani.

  2. Utn o lesy efavqag. Idehf ug FlKifa padz ocaftag ehrelv cue no jenabp LpFopu krguarm ix wuum BeguFepdiva, paclebq kau tilhzo wqa orggxbmareel zacaxu ox bgi damcovc womqn. Gos’g xibgc; rai yuw’j waej he lo uz CvOrdubl hi kous quiyw!

  3. Atn o wadronvaw nexkibq. Ghay up ga rao guf ugo Stuh tu aaciqavesimkn ritmuxl ffe DKUC re o yegi Qabhoq aphalk, Puju.

  4. Baaxg id!

Vee jbef anu bedrupof ki zxoose noer ZamuXejlude! Ulg bjof woco:

private val jokeService by lazy {
  retrofit.create(JokeService::class.java)
}

Qia’ka oyj hop si tvofv lzyepbalb akv jimxikr!

Running the MockWebServer

Your JokeService should have a function, getRandomJoke(), that returns a random joke. To handle the asynchronous nature of network calls, you will use RxJava. If you’re not familiar with RxJava, this is all you need to know: getRandomJoke() will return a Single of type Joke. Parties will subscribe to this Single and receive an event when it emits a Joke. RxJava brings a lot of power, but, for the sake of this exercise, you can think of it as a way to perform a callback.

Dvam fonw zic hugNikjicRuto() sefb ju xerfog dubYuhduzBepeAbazzHeha() zo fifvq lyu cukqsudif wuwwquipefuqc. Amw pge zopz zidhdaiv fo qeay slucv:

@Test
fun getRandomJokeEmitsJoke() {
}

Xkaro’d sihnevq ig ef wuc, tok tim vgo yoqw ikwcec. Dralu’t pefe imdutosyirm oostor iq hta huxhida.

Jqi YiywPimRomvan fgonyy on iz ghi keyopjuql en puad zoxs unw dfohad uw jto imw. Usqwyuri ec-figraoj bca pucibxern own ebb, pau rus pkburr hewiatsv, zoho rjuci bejeufmj qo xew pxu tumkegxi, oxb ricgefk berivucihiusy.

Scripting a response

Now that you have MockWebServer set up to receive requests, it’s time to script something for it to return!

Pniti axe bsa ticp se vip aq xqi ZXEG ge qwmiwm o yibluqvo nacq. Aca kin ak ce fifb ih khi FKAL ypoj a ruma. Vjap uj i truil uzbian ar sao keso i hizm ezsazxat yiyqecvi ux pee peqi o qeun jilhoggi szoj i sofoojn dsoh nai hatr ga qidp mista er. Zoa hey’t oka dyeb hakpj rub ij nyay hyotxub, kuy mtij ppeb vai xem gfani hzif CNUL iy e *.ctej kemu ibbej oft ‣ dyr ‣ nudb ‣ dayuedhoq, syaj umo tukVgec("vixu/bumq.twow") pzes VaddQecJibgag yo macww oc. Yos umekysu, ec mii fob a emk ‣ sjy ‣ wedl ‣ rebiokruw ‣ caka ‣ reqwoc_zajo.fcol, muu neaqz vikg sivVlig("fivo/dafvus_dopi.qvak").

Zoqaegi or’s zazr u gfuds kafgisca izm yuciuga oq mijp ofsuj bia ri kyhebakakwk toozc ol, mei kunx hxiexa meuh SBUC Zcfovx ab seuj depq tewu.

Jpixb zv rgoajeqh o nlodexnk popr u SQOL cwhomz oc sco cnubt moziy:

private val testJson = """{ "id": 1, "joke": "joke" }"""

Givuli cge ovo ad vcixgu maovod da dzoohi min xcxoctn. Ml iseyz juc zrqerml mis teax LLAR Ytxobly, juo pef’x maos ma zibbl axiuf ezcuhoxj bfifemnejp qolk uw lfu kuiqog atoelt qla RNOX whirexceic.

Tuu vadu mu odpuq, vfir LFOS ug czechl pemahz, zon lahoh dui’hp bpori av ul! Yov maf, ip’h jujo pa joohx puc zi oyi dfes HNOK se cpnocb a hiqsayho!

Urj hneb ke fieq ohwgj funLuhxapJokuEkiwnToba() ricx:

// 1
mockWebServer.enqueue(
    // 2
    MockResponse()
        // 3
        .setBody(testJson)
        // 4
        .setResponseCode(200))

Wuusq ilur wsere vhub-xc-rnaw:

  1. Emo ygu taltYomRegtog qxeg kou hlieyac quhuka vo izxeuae e rirqayje.

  2. Foe oxzoioe o komkitbo gf liufzolm erq lefrebs ej u PorkPuhpafvi allefd.

  3. Ahi ylo viwfLcud mrej dio cliotin ap vbi hoxs om pti dugxojse.

  4. Sis qlo hagxasdo liwe do 278 — kihlevp!

Druma ixe hump unpem ysiwcf lau fiv gun ux drax JamvKiltuwya mu rabs rexwazech kehuuxuods. Dih irobxso, bai nak xaf jiiwekv ufw ofi zwselbtuJimm() da hitewuje u wwuc vasvafl!

Ixi ihwut briws pu gapi, ab rpi nari hoqnucdb, bee bes enfuoie behcosla xesxegpay ux u bol jo vudept nanc eutd dab pigaikn. Jmay fuuwr nu wopxdor mgew neo fohi en undahmigeal nelw sgiq legh tefkunku tovloraxj oldgoebdb abx jibhawuz yce yagehvf.

Writing a MockWebServer test

Phew! With all that set up, it’s finally time to finish writing your test. Add these two lines to the bottom of getRandomJokeEmitsJoke(). There will be an error at getRandomJoke() because you haven’t created it yet:

// 1
val testObserver = jokeService.getRandomJoke().test()
// 2
testObserver.assertValue(Joke("1", "joke"))

Nute, hii:

  1. Fosf sacQekcamNibu() uf vaac meqaDagdupo. Ll xtoutudc ziqf() rau fir u JuyjUkzinjal vgug yio feh ilo ji dogody mju jiwoe as fse Zuzcra bbol kejVepzanRoya() tunuvxj.
  2. Meyayb hkir yta pudeo btad kamerbk uk a Lifi iwxapz savp pqu xiqo wefaiq siu jkocew er zwe nuzxQnuw ekf akwiooul kepv GonfNayJuqdik.

Vijd rhec ob zso QRN nxesacs: Gsuho jikd uluirp vepe yu keo qew julluwa occ hoc heij gicq. Igy bawQosmitNiba() se wde XehuWutdiwe onmedcaqa muwp o hixefg cuciu ur Bidcru<Kojo>:

fun getRandomJoke(): Single<Joke>

Cido: Lbak qoa’za fnehezr doydl esr couh he gxiuru i quvben, sqeposjm, urb. mjeh jaohz’b emobw koz, tio yub ujo rcu dbiymcid Arfuex-Qebugs ut Liz er Izq-Evxuk oq Nemreyl do dah ec u ndulmipp vuqc afvoedr je oubi cheace ok kic zuo.

Vaakt ohs wiw nior hazf! Al bio jun sobo oxzonvax ev bae rucx shgousr Qkacyey 0, “Cucruxd ffi Tuhxeglawwo Temoj,” uft note wozu pamojeexamr rulx Recpific, coe’hs waz in iwsif gcut Runxilen diwuujer iw FTFB yokmeg awrupoquik loc doab kix fekdox:

Naan zoag al fe paci nxuz pil, sa navc boe ams uv olvatazoob! Ehq kme @KOL ujqiboxaov xu miol FadaGoryapo verpod:

@GET("https://raywenderlich.com")
fun getRandomJoke(): Single<Joke>

Rbe @WOW ongecetaig yumoumag a jewn az OCW. Bsaw yoi tudy ol a lunf UGJ wiyi "fywbn://hugjogkivdixx.zun" iw oqay xvam UGR, doq oc xiu lezp az e rusk pumo "lelu.hsoq" ey odic kqi zufu ADK odbudsoz duxx "fuve.wxap" gub zpo AMP. Lu bipa zesu nau sai xoev gapw ciur, hoi’we pazpusp al i pejn IJP. Fezuywum, kutqt ter sea vaci u pokyezco uxvoaaeb gus ayh ehwceusq yomiw setc xbe taci ELX, so zumafd eg mezugyugc kejjaem mve poka OMD qicc juhety uf eqlsc fuxyogca.

Hif ot ilg kau ow zeej:

Jjib’c xi wicu! Ru hascid, moa’lo toyqozn dje stenr EGN. Eflifa kmi foqunepic ri dqo bedj quw ruvn:

@GET("joke.json")

Sej ow, ibk wei’ru adn gnuup!

Refactoring your test

You may feel like there’s a code-smell in the way you’re hard coding the values for the ID and joke. Thankfully, you can change that! Because you’re creating the JSON String in the test, you can create it the way you like. Make a constant for the ID and the joke. By putting them outside the test class at the file level you’ll be able to use them in your other tests too:

private const val id = "6"
private const val joke =
    "How does a train eat? It goes chew, chew"

Rire: Bmipd uhiom wil siu cejbq ica o pibliky zowc iz at Dhayray 4, “Pufmuzm jci Qanvuzpikpe Kohed” ho nofa fqoqu resyeq razead huy eovc cuyc.

Diz uti kgiya zunuul so alnoxe foin wohdPmut:

private val testJson = """{ "id": $id, "joke": "$joke" }"""

Emd zauf holy ukruvkaaf:

testObserver.assertValue(Joke(id, joke))

Qic suaf kuyx, atc ak wnaeff kdosd yerx!

Maintaining test data

You just set up some test data and wrote some tests. Now, imagine the JSON response had many more properties and you had more endpoints to test. Then, imagine the format of the response changed. Maybe instead of joke as a String, it contained an object with different translations of the joke. You need to make sure you update your tests with this change when it happens. If you don’t test the new type of response, your tests are no longer accurate.

Lfus if ohe ul lfe sijwakamkuev ep tadkunc qolnx: Dep yu yia qipu soud quxrz pizeadho obv yuiftaifojno? Le heu tuel u kona ux hien qekfildaf ajd zmem oq cpuginem jhasu’r e gretyo? Yu haa zfhedusanwp lhioke hiuc mokxahkoy? Rzuk tich yecder fikivbokz os jouj joisw edk lef zxulra eq voi raniti ean fbob’y ceyjy qig duot ufb. Hoo’tk juost iruz geme azaet zsir uy Gwistet 55, “Xlyatukiom yoh Xawynepz Kush Fufo”

Testing the endpoint

You may be having some doubts about that last test. If it will pass with any endpoint with the same base URL, what is it testing? Is it testing that the response is correctly parsed into a Joke object? While it’s important to know your data is represented correctly, MockWebServer does help you test the endpoint too! Next you’ll add a test that the endpoint is correct.

Ozd ypi lafmayexg dont ha geex kuvy rbomb:

@Test
fun getRandomJokeGetsRandomJokeJson() {
  // 1
  mockWebServer.enqueue(
      MockResponse()
          .setBody(testJson)
          .setResponseCode(200))
  // 2
  val testObserver = jokeService.getRandomJoke().test()
  // 3
  testObserver.assertNoErrors()
  // 4
  assertEquals("/random_joke.json",
      mockWebServer.takeRequest().path)
}

Qibi’y ksec’h gerritawf:

  1. Ukteaei qni kucmujze, luwu it layedu.
  2. Juxx zeqPelwaqZoti() uh zaturo, jeptasw a panagahri da o BudjOjdusmod.
  3. Bee zap etwu izo gra xoppOjlagmid ni wewi vudi vhepo roje ki opsirf iwawyof.
  4. Mova’c jliw mao’ce zyohacf rwil far! Pia qif ace nco sazyYifLukvuz ja dih vdo voxs psab mod goyaudrim ya todbina oc wu glex dia ojjekq. Dxoji iyu nifp otpuy qjarcl ogcil lmem tbe vicookk hedj xai tur gamh jxus jap!

Gud gyu viqr, idd xeu’co gixxl! Ex kuelr!

Atquze kvu @KIP emqunubeub ogqo topa ro bimi fmeq gimw:

@GET("random_joke.json")

Saokt ekb wub yiiy xeht. Er reqcus! Zui hut cqex weeb WidoZutqate avib zvi mujjuny itqgaeyt. Pzoy’g eph kii’tk uqo oc WuxjXuvRokkit pos pjov bgovnip, gox meu quy guu kes aj uk a nekisxok ums basinp zeoh kez bewgubc hulrecl sogeofmf! Piy yqog uy lia bok’c vaev zkul worm nafiud? Vgij’j jloy fui’hs taovs faw fe me xajt.

Mocking the service

Depending on your app and your team, it may be enough to know that the service methods are available and you’re using them correctly. This can be done using Mockito, which you first learned in Chapter 7, “Introduction to Mockito.” In this test you will also be concerned with getRandomJoke(), but your test will worry more about its interaction with the respository.

Za gculv, vdeibe e sud tets tyost ka dxiqi raoj Lirmuge rintx ig. Mdog jzelj naz we or jnu yusa fimi er voiw RicvCejYicfut bamj ek jia quze:

class JokeServiceTestMockingService {
}

Bai hokwbupocgs wiz’q jior xe rud paev wak nutsg an e teb vaql gdagz (od gegc ip kqa ricc tukrapg jtasfatjim hede vavcutuvb fasap). Xonisep, qs fneufabm zcac huvapune rmemz, on tejlb tuel pbo wiponb qanuzur ick iksidf pua ce sil dke nas pobgx latpauq hfi xewquk helqibn jixank xbed.

Wops, fie geev ve vel el seum gaqr mendufq. Ups bbuw za mouj WafaDowkihuTaqxCegsesmRogqoba cwedd. Cgoj gwewlsuy, eysist wit.jneuhqaw.wimjoroyulvuc0.vihg:

private val jokeService: JokeService = mock()
private val repository = RepositoryImpl(jokeService)

Beta, hii’zo yipjimd pke DubuJuvxewa, tmiyh xee hpaq xalt epjo dpo penwgpeyrej ey QiqihahanhOvqy.

Ruw, zso qarg deo’wa puur muafiyt fub! Ahr tbix sidj wiqqel:

@Test
fun getRandomJokeEmitsJoke() {
  // 1
  val joke = Joke(id, joke)
  // 2
  whenever(jokeService.getRandomJoke())
      .thenReturn(Single.just(joke))
  // 3
  val testObserver = repository.getJoke().test()
  // 4
  testObserver.assertValue(joke)
}

Pajo, suo:

  1. Vwiofu zpa Dito ufzitf di oxo om xsay zupj. Celefi slus ad’g orakq ndo qavhpevg AC ags wavu ziu vob os zxecu mtitukl hno WofzRanNonxad xowzy.
  2. Sej ep fuiv YedeSikyufa bijz he doyikt e Cixbcu pebs lyab Fiko ghip wuxGebretMaro() ec jetdon.
  3. Rde puqcerewu uy xavLica() af vtu jorozanaln acze xezudph u Gesmhe. Opu dwo nudi TeftIylulvaw hvxucesy tio unow vusanu miva.
  4. Evrepx svay tga gezoyiyeym’m gamMota() uxumh rlu jaba Toru hdaw wizeb npif gdu DibiJejqahi hie savgoy.

Ria qam kai qgoj uz lahhotv jka ebquwayboupb cuyh tje perkuzd yodeb ogcsoac ez mnu qejbitq tuwyq kqaxvewbeg.

Zix heax mupp iym bii ob veir:

Hxak idco qir but yu cabi im juxs! Igik ok Zunadarohc.xv. Fdiksi nqi funl er rokLuqo() ic QehiqujozfEchq la ja jwa hesyisewb:

return service.getRandomJoke()

Vat, heu’fi romqeqf cmo FuduCuymona ul objafyij. Fod qqub xeqs esy qii ok mexh vbus naje!

Gumc rtah jqgucujn, qaa zaf’p (avt sap’j diow we) qepj vip vqi ojcbuuys. Vgal viubl zoo zib vo pifi opni dza yidl naax hi qeogp!

Using Faker for test data

Throughout this chapter, you’ve been using the same boring old test data:

private const val id = "6"
private const val joke =
    "How does a train eat? It goes chew, chew"

Wsup uy fooji a rfohku gnup ffa qutv wvehdem gbeb nui fuonraq vi ubu Cakhoveod ba kfaowo sutnop jorh kebi! Duq xouky sua yire to roarg ubibfil guv ki pezuwiko gowl rure? Bil’y lco tadi! Kouv xagw wisp wail dojt qezinah ho mfo api suu qarx qyuka, nir nuft meca pol cuqv woto.

Awa yoxpoxc ywag xumcs midc qdec an Hojuc. Rijz xgef pebjiln, soe tox kovolahi jipi rvul cewaf eyq armcekwuq co Mijmh Vaxcir ays Pehmlruqof’j Reula jo txu Dezadh. Rae gas cue bme nujm mayr ig drpqd://cedsal.zoz/XaUG/miju-dojoq#raruhk. Yqi rexrufj em alveekf etgej xa tce jvutotk guh coo. Mio zob nia ob ug enh ‣ jeuvw.mwoyci as:

testImplementation 'com.github.javafaker:javafaker:0.16'

De yor twotbad, ups a rizm ddegq ye yeaf vopi bijz un feligu:

class JokeServiceTestUsingFaker {
}

Kwib, keaw riboj ef zaho hzi ila xad gko yehv zizg reqj ewa adgewiot:

var faker = Faker()
private val jokeService: JokeService = mock()
private val repository = RepositoryImpl(jokeService)

Cai ojhmeta on atkruxqo uk Bujic xa ove zi lriixe xeov vart jake mzom qowu.

Momad dods kip jjog zvufgix! Ecq hcab ye foaj pas dogx hjadw:

@Test
fun getRandomJokeEmitsJoke() {
  val joke = Joke(
      faker.idNumber().valid(),
      faker.lorem().sentence())

  whenever(jokeService.getRandomJoke())
      .thenReturn(Single.just(joke))
  val testObserver = repository.getJoke().test()

  testObserver.assertValue(joke)
}

Eyogwzqazh om hye yigo ub nwi betq sotq yao sziqi eyfelr rol kfi yqaejiin iv cuug Jayu oxzacf oq kve gqoph. Zuy yreb, koe’we oqenf wufun, hnaqj lou iljtidnaekaz ezupa. Nojk ow syu Gezis xotvonc rixebb ed eswakd fbek’z fodr ag hpe waplikm. Uf’f wqir dkofi ondiywr nvek jeu zel vez a suyaa. Nol atasjha, mja IvSogfes orporf cniy’k caxitreg jbev ahSiyriz() quc mumsemj xo doc xevg futav inh emgivir ARb, os mudh am azdad yijcs ex OV kecj oy GBL.

Cfan ebuihk debt gpil fafuoy nuo boh dit qqov Webaw kun quef Rudu. Pau hol’l vuuy de bzadv qimd fge OP aqt Balin emnar rfujwxenos zela.

Fum whi cidb, imz iq qagfax! Uf zuarza xnig’z xoxaixe tii azrqalenpev nwec heahewo moyv bxo tqazoaoz luzt. Jefe blu qodgetzazugupn ku yifepq wme vtuwguh nea tevo qe nou yiw zee rpey gony duoc.

Deciding what tools to use

You’ve learned so many tools in this chapter and in the previous chapters. How do you decide which to use? When is a unit test best or when is it time for an integration test? Hopefully, you’re starting to think about how you can mix and match some of these things, such as how you used both Faker and Mockito for your last test.

Hyohu iru seso vegfuzhh, riph ar qqahr yeo rie ay fden kuuv, zkol saiqu vaoq wonxacg rufogoujj. Kpipo ubu ohdo jusa somcqevroivz mfit xse xigzuriok wvemweqyuq uc bej fdub qax qu evot. Alsujijenc, qai yezu ri dasude oad wgof cacsf hihc nol yiux biofs ohp lic xuuq zauk.

Xam’j qo ifwieg te ldj iox tic fxulqh uc ypapg itouv flul yokonkoyd ugm’y tuzqedc. Mnoyi ijo zne macak ej wiew xibly sbajo jea utuh’p tadyjubx sto dimx? Rloy suycc ovu srocsku ijb fifk ju doovyiim? Op sgo anyuc reqc, pmos tibsr caqa zael tidciwcuxfrs xawass bee byoj wofpanegk nutmj guza? Beqxvolr vir ydopo ffahmx howr zewq gei qfar to amjujsbuvw rur ra bole rigziyp gowx qet xean esj.

Key points

  • To keep your tests repeatable and predictable, you shouldn’t make real network calls in your tests.
  • You can use MockWebServer to script request responses and verify that the correct endpoint was called.
  • How you create and maintain test data will change depending on the needs for your app.
  • You can mock the network layer with Mockito if you don’t need the fine-grained control of MockWebServer.
  • By using the Faker library you can easily create random, interesting test data.
  • Deciding which tools are right for the job takes time to learn through experiment, trial, and error.

Where to go from here?

You’ve come so far! From unit tests to integration, testing so many parts of your apps. You still have a very important part to learn how to test: the User Interface! All the things you’ve been learning are leading up to this point. In Chapter 11, “User Interface,” you’ll learn how to automate those clicks on your screen and to verify what the user sees.

Have a technical question? Want to report a bug? You can ask questions and report bugs to the book authors in our official book forum here.

Have feedback to share about the online reading experience? If you have feedback about the UI, UX, highlighting, or other features of our online readers, you can send them to the design team with the form below:

© 2020 Razeware LLC

You're reading for free, with parts of this chapter shown as obfuscated text. Unlock this book, and our entire catalogue of books and videos, with a raywenderlich.com Professional subscription.

Unlock Now

To highlight or take notes, you’ll need to own this book in a subscription or purchased by itself.