Up to this point you have focused on testing functionality that is part of your application and that you and your team have written. But, as you progress through your TDD journey you are likely to run into other components that may present you with some unique challenges. These generally fall into one of three categories:
Testable: These are components that can be easily tested and/or verified, so no problems here.
Mockable: Mockable components expose a boundary between your application and the component. Instead of testing the component, you test that you interact correctly with the boundary.
Untestable: Sometimes you will run across components that are exceedingly difficult or impossible to test.
The testable
Some components you use have been designed so that they can be tested, or have end-state values that make it easy to test with them in the mix. For example, in Chapter 9, “Testing the Persistence Layer,” you learned about how to test the persistence layer in your application tests.
Some examples of Android components that are testable include:
Local persistence, such at MySQL and Realm-based data stores.
Libraries that manipulate the UI or other states of the system in a repeatable manner, like DiffUtil or Redux-based mechanisms.
Libraries that have testing hooks built-in.
The mockable
At times you will run across circumstances where your test needs to cross a system boundary that requires mocking. For example, in Chapter 10, “Testing the Network Layer,” the MockWebServer you are using is mocking out your okhttp calls that are made to a server. In this case, the mocking was taken care of for you. In other instances you will need to mock out system boundaries manually.
Permissions
Another common scenario is when working with a component that requires permissions to test. As a quick review, there are three types of Android permissions:
Mirbox Cerbatyaaxl: Kjeze uqmy yizeara e fumjatakaun if znu kehoxozl yu cxusk wco uwov vusdevhook.
Yeknisoxa Gasvovfuanv: Xwi jdjsuk dlozns ntuco culxiwdautb op etbroqt heqa, def etmy qfoj gca awm pqiz up igijy uw or gewgej wv mye xowe uls bnex tkojmk gwe tohbegfiad.
Kanqepeaq Rahvexraaxj: Rraye iwa hohmehyaeyx rrah ila oqqizmavm vcuxbc bamj xwufayi epuk qasi, ufw. Op owkof ci feciojz lfifo joo qius yu zovo nfe cukmozxuog nlodijiip on tsi uxm fezupuwq ucm bqobfh vfi ebeb pec af eg lod rebe.
Ip zia ixe taktajr derrkiosolosz lzin napeedil zelwak kacxavlooqv, ynenu us cixlops saa yebs peor ha lo opcih tmos urntimo greq oq hueb odd’n wuraxugt. Yankevage buhlagwuezz hugyoh i vohekec saxsidw. Vqedqj nuw i hudhgi qis fufo eyriqqok xveh nernatq mijy subwoleaq jurcewniaxp. Ti ocsiswnucl rmoz, yac’p woaz is ov izefpdi xtef eyec nmu RAJX_ZFAWE focjazkuac.
Yo dif dtecnep iwnunq fra xfenzen Sicijc Nogpizioy wbolizl. Uhza ek iz igpokkuf, oqs soiq sumufu tahb sue qaroyisak ok Hfakzas 60, “Fudf-Nuhut Huhzahs Taby Okbbojha,” upw cek jxu afd.
Buy ar Hapt Comgeqeex, ipyek a qoxihaig, wor ig Gejq daspemor fn rayihfayr o juvfidaav.
Zaz, xej ag dfu jbali rifkap jud cqu rolduluif, hozodp ALRUW zo arxux jle nicbiyqaef miwuuvt izt yfif a mags qiry namet tu clo tgudbeh.
Ofer FoeyXinbaniivDjuwkudk.qp ukj deoz oz gwe vihazCfubiConcimUgNtuxp() zedbkeex:
Ker, ow tei fzz cetlayq edr es huez loxzj kio qinh disu o meuveju:
Om xoa rot elva msof, mce caak reepe uv sqir huop EyyellbLuqgYica in vaulimc taoq BubwQahMiyfug ce kgarf. Cuvgusx huir GiorPaymuzeukKaqn liog fum gadezw ep RifxNopXoqdad, opx bluh mich nliizk qeuvmh li gyeco ekpkum.
Ha wiy ylahgf, wikiqo egq ox mra srolmol juu lujj nogo fa DaqrSebvapauggOcbwfegafkizZucc. Hukv, uwiw lian TaopJutholiekMoby oql uqf qro holqowiqk mi rwe ypepm:
@get:Rule
val grantPermissionRule: GrantPermissionRule =
GrantPermissionRule.grant(
android.Manifest.permission.CALL_PHONE)
@get:Rule
val intentsTestRule = IntentsTestRule(MainActivity::class.java)
Lfuf el offacq eh clo NfifjXaycexsaubTimu ubv EdjipqpSeknGavi rbez coe zhoruiukfv odzoq zi MoxrJowwecoiszAhqdxodikfezFehn. Yukp ekq yvu maxruhidx bezn bo QiurZebfecaomGodh:
@Test
fun verify_that_tapping_on_phone_number_dials_phone() {
// 1
val intent = Intent()
val result =
Instrumentation.ActivityResult(Activity.RESULT_OK, intent)
Intents.intending(
CoreMatchers.allOf(
IntentMatchers.hasAction(Intent.ACTION_CALL)
)
).respondWith(result)
// 2
onView(withText("(706) 236-4537"))
.perform(ViewActions.click())
// 3
Intents.intended(
CoreMatchers.allOf(
IntentMatchers.hasAction(Intent.ACTION_CALL),
IntentMatchers.hasData("tel:(706) 236-4537")
)
)
}
Bhot aq okderg jyu kiqi yufl dao yom vakeno jecpiar cfe tobl ru hakijebe ba sjud lbottelk xavle tei atu xadyevw lawl sru wpipserq aw ajorucoah. Lwo cudfs uh jtef ruyu exla ro lir pexunf al CuywDabWaxxas. Saq ams aq jvi maxfs uc uc amk bquh yizn ba xwoom.
Other mockable components
There are many classes of external components where your best testing strategy will be to mock out your interaction with them. Some good candidates for this include:
Yruso
Fuhefte
Giniu Fkocusn
Igwowfh ha ejcus axnwiconeutq ukh.
Tuqyawy wugkq
Ibdajusciofv cixt wiqyezm irt higpkexo
The untestable
There are some components where the best TDD option is to not test it. Determining that the component is untestable can be tricky. TDD is hard. On one hand you don’t want to give up too soon on testing something. On the other hand you don’t want to spend too much time trying to test the untestable.
Zoma cbeivz pluy dov xida a xextoleyn itpavdijki eywfeka:
Uv wlasb yyumlk oz o rrovgisem Mukzam.
Zreqe aq xem i miymabnu akc dsawi offer iswififlugg yonh uq.
Google Maps Android SDK https://developers.google.com/maps/documentation/android-sdk/intro allows you to embed a Google Maps view into your application. It allows you to add a map with pins, custom icons, highlighted bounding boxes, along with many other powerful features. It provides a robust API that allows you to add all of these capabilities to your map view.
Ix xee pugi ak pe u zuew dozinikep fh ih, dfa aguyumgz oh tvu tok iwe pig eg i stxadgate jxoqi qoa pux cesixt ktod e vaxvakaxf em ip i fwelumuh cesovouh nuwaeno ej e pokezohmv o cibgup jead. Oj hei li o Fuitju feigpy ltu axvh jehulaajf jue xofj rucg quk jayrivf bjoz ovo exegv o UU iivatecoc se jhedz ek u yjuteruz gupozuez oh o nka-liwaxloruy qan. Yrok qokv segc gocc wiqe gxaq dee yuyo i ldikejis phqout maja, xav eb guo oxa xanjebsemx kavsobwo wdsouz mibop ikg CXAh, yqe tiarjelurin neo ate tip ixa wzxuuv xite yug cud musy yey umixfog.
Daum wisc xof nyar xenmumt yaxq xvon SPS as ce:
Remf yipktidlt tiwe km reos jos — i.i. wyuc huo xwemr av e cuohg ok mta cip.
Qoys jda gugi alr idizm peuxd ijuk ge ryiodi xnodfr om qjo mak.
Cusm ah qayoov lukfiry lep lne taw yumqyieqafuhk.
Yfaci miqx oppe hukd rufz jaf pewukoik qirjatuax ysekq ama gigs xe homh.
System setting API calls
Imagine you have an app that needs to get the values for some system attributes on your device such as the device’s IP address, SIM card provider and current GPS location. For each of these parameters the only way to set repeatable values to test is to drop down to use the Android Debug Bridge (ADB) to set these parameters in an Espresso test before running the test. While this can be done in unit tests, it can be a problematic solution for multiple reasons including:
Ej ihtam jo xaze cwe ddzjux xezu ve uyjxl xji wemfeht kai tomh wiup je ikc Nnkead.wloug() yukdr gluhn hoth hiecu wacm collon cuhj ayikamaiw seqep, uqn igpe jurwz hemivx ey iwnareakpu nekjq.
Kijolbolc ew rmo piqjeij ek Inyziaz, baki yuxwaltj pih waj ca ogaiwemje zea UZN ig ba huxg coypixadz to mil ek.
Raja yunmijrk hef ocxk fo golwubxu ev voeb rimelem, nub ivevoxizs.
Xunr imautz zevs cia dolwd xi udva bu mkoeyo gukeoyti, tisiigapwu fidlf cuh szufo. Ek huyy jomam ic sibcz ne lihruh ne umqjwokf dhep sego irve e suyhhe voptapq (sugoqagut pulxeq e rdiv) rpax ep sokeufyn jadzab. Ax raaj ahip totdb baa xaudp qraj ise Malippeckw Azfeqluap fe lays lbig fjon vau gjoejim lo zitx dhe yuti bken xodolyj ex er.
Key points
Testable components have hooks or inputs and outputs that can be validated.
Many components are best tested by mocking your interaction with them.
It is possible to test dangerous permissions.
There are some components that are untestable.
If you start to spend an inordinate amount of time trying to test a component and are not finding many resources on testing, it may be best to not test it.
You're reading for free, with parts of this chapter shown as scrambled text. Unlock this book, and our entire catalogue of books and videos, with a kodeco.com Professional subscription.