package Ġcom . ako ch dev . mar vel list . view model Ċ Ċ import Ġandroidx . arch . core . executor . testing . Instant Task Executor Rule Ċ import Ġandroidx . lifecycle . testing . Test Lifecycle Owner Ċ import Ġcom . ako ch dev . data . database . model . Character ListItem DB Model Ċ import Ġcom . ako ch dev . domain . model . Character ListModel Ċ import Ġcom . ako ch dev . domain . model . Result Ċ import Ġcom . ako ch dev . domain . use case . Character List UseCase Ċ import Ġcom . n ha ar man . mock it ok otlin 2 . any Ċ import Ġcom . n ha ar man . mock it ok otlin 2 . wh enever Ċ import Ġkotlinx . coroutines . Dispatch ers Ċ import Ġkotlinx . coroutines . Experimental Cor outines Api Ċ import Ġkotlinx . coroutines . run Blocking Ċ import Ġkotlinx . coroutines . test . Test Coroutine Dispatcher Ċ import Ġkotlinx . coroutines . test . reset Main Ċ import Ġkotlinx . coroutines . test . set Main Ċ import Ġorg . junit . After Ċ import Ġorg . junit . Assert . assertFalse Ċ import Ġorg . junit . Assert . assertTrue Ċ import Ġorg . junit . Assert . assertEquals Ċ import Ġorg . junit . Before Ċ import Ġorg . junit . Rule Ċ import Ġorg . junit . Test Ċ import Ġorg . junit . rules . Test Rule Ċ import Ġorg . junit . runner . RunWith Ċ import Ġorg . mockito . Mockito Ċ import Ġorg . mockito . junit . Mockito JUnit Runner Ċ Ċ @ Experimental Cor outines Api Ċ @ RunWith ( Mockito JUnit Runner :: class ) Ċ class ĠCharacter List ViewModel Test Ġ{ ĊĊĠĠĠ Ġ@ get : Rule Ġvar Ġrule : ĠTest Rule Ġ= ĠInstant Task Executor Rule () ĊĊĠĠĠ Ġprivate Ġval Ġuse Case Ġ= ĠMockito . mock ( Character List UseCase :: class . java ) ĊĠĠĠ Ġprivate Ġval Ġlifecycle Observer Ġ= ĠTest Lifecycle Owner () ĊĊĠĠĠ Ġ@ Before ĊĠĠĠ Ġfun ĠsetUp () Ġ{ ĊĠĠĠĠĠĠĠ ĠDispatch ers . set Main ( Test Coroutine Dispatcher ()) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ After ĊĠĠĠ Ġfun Ġbreak Down () Ġ{ ĊĠĠĠĠĠĠĠ ĠDispatch ers . reset Main () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġfetch Character List Success () Ġ{ ĊĠĠĠĠĠĠĠ Ġrun Blocking ( Dispatch ers . Main ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhenever ( use Case . get Mar vel Characters ( any (), Ġany ())). thenReturn ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠResult . Success ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcharacter Database Model List ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) Ġas ĠResult < List < Character ListModel >> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval ĠviewModel Ġ= ĠCharacter List ViewModel ( use Case ) Ġ// ĠThe ĠViewModel Ġcalls Ġfetch Character List () Ġon Ġthe Ġinit {} Ġblock ĊĊĠĠĠĠĠĠĠĠĠĠĠ ĠviewModel . character List . observe ( lifecycle Observer ) Ġ{ Ġui State Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertFalse ( ui State . isError State ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertFalse ( ui State . isEmpty State ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertFalse ( ui State . character Data . isNull OrEmpty ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġcharacter Data Ġ= Ġui State . character Data ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( character Database Model List , Ġcharacter Data ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġfetch Character List Success With Empty Response () Ġ{ ĊĠĠĠĠĠĠĠ Ġrun Blocking ( Dispatch ers . Main ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhenever ( use Case . get Mar vel Characters ( any (), Ġany ())). thenReturn ( Result . Success ( null )) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval ĠviewModel Ġ= ĠCharacter List ViewModel ( use Case ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ ĠviewModel . character List . observe ( lifecycle Observer ) Ġ{ Ġui State Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertFalse ( ui State . isError State ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertTrue ( ui State . isEmpty State ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertTrue ( ui State . character Data Ġ== Ġnull ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġfetch Character List Failure () Ġ{ ĊĠĠĠĠĠĠĠ Ġrun Blocking ( Dispatch ers . Main ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhenever ( use Case . get Mar vel Characters ( any (), Ġany ())). thenReturn ( Result . Failure ()) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval ĠviewModel Ġ= ĠCharacter List ViewModel ( use Case ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ ĠviewModel . character List . observe ( lifecycle Observer ) Ġ{ Ġui State Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertTrue ( ui State . isError State ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertFalse ( ui State . isEmpty State ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertTrue ( ui State . character Data . isNull OrEmpty ()) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġload More Success () Ġ{ ĊĠĠĠĠĠĠĠ Ġrun Blocking ( Dispatch ers . Main ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhenever ( use Case . get Mar vel Characters ( any (), Ġany ())). thenReturn ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠResult . Success ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcharacter Database Model List ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) Ġas ĠResult < List < Character ListModel >> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval ĠviewModel Ġ= ĠCharacter List ViewModel ( use Case ) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠviewModel . load More ( forced Ġ= Ġtrue ) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠviewModel . character List . observe ( lifecycle Observer ) Ġ{ Ġui State Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertFalse ( ui State . isError State ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertFalse ( ui State . isEmpty State ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertFalse ( ui State . character Data . isNull OrEmpty ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( character Database Model List . plus ( character Database Model List ), Ġui State . character Data ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠThis Ġtest Ġis Ġtricky Ġbecause Ġof Ġthe Ġnature Ġof Ġthe ĠCompose ĠUI Ġframework Ġwe Ġdo Ġemit Ġseveral Ġvalues ĊĠĠĠĠ Ġ* Ġfor Ġthe ĠUI State Ġwhile Ġthe Ġmethod Ġis Ġexecuted Ġ( this Ġto Ġreflect Ġthe Ġ" loading " Ġstate Ġon Ġthe ĠUI ). ĊĠĠĠĠ Ġ* ĠThis Ġis Ġwhy Ġwe Ġhave Ġan Ġ" if " Ġwithin Ġthe Ġ" observe " Ġmethod ĊĠĠĠĠ Ġ*/ ĊĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġload More Failure () Ġ{ ĊĠĠĠĠĠĠĠ Ġrun Blocking ( Dispatch ers . Main ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhenever ( use Case . get Mar vel Characters ( any (), Ġany ())). thenReturn ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠResult . Success ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcharacter Database Model List ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) Ġas ĠResult < List < Character ListModel >> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval ĠviewModel Ġ= ĠCharacter List ViewModel ( use Case ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhenever ( use Case . get Mar vel Characters ( any (), Ġany ())). thenReturn ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠResult . Failure () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ ĠviewModel . load More ( true ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ ĠviewModel . character List . observe ( lifecycle Observer ) Ġ{ Ġui State Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( ui State . isLoading ) Ġ{ Ġ// Ġread Ġthe Ġmethod 's Ġheader Ġfor Ġexplanation Ġon Ġthis Ġ" if " ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertFalse ( ui State . isError State ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertFalse ( ui State . isEmpty State ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertFalse ( ui State . isError Loading More ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( character Database Model List , Ġui State . character Data ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertFalse ( ui State . isError State ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertFalse ( ui State . isEmpty State ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertTrue ( ui State . isError Loading More ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( character Database Model List , Ġui State . character Data ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġval Ġid Domain 1 Ġ= Ġ" id Domain 1 " ĊĠĠĠ Ġprivate Ġval Ġname Domain 1 Ġ= Ġ" name Domain 1 " ĊĠĠĠ Ġprivate Ġval Ġdescription Domain 1 Ġ= Ġ" description Domain 1 " ĊĠĠĠ Ġprivate Ġval Ġpicture Url Domain 1 Ġ= Ġ" picture Url Domain 1 " ĊĊĠĠĠ Ġprivate Ġval Ġid Domain 2 Ġ= Ġ" id Domain 2 " ĊĠĠĠ Ġprivate Ġval Ġname Domain 2 Ġ= Ġ" name Domain 2 " ĊĠĠĠ Ġprivate Ġval Ġdescription Domain 2 Ġ= Ġ" description Domain 2 " ĊĠĠĠ Ġprivate Ġval Ġpicture Url Domain 2 Ġ= Ġ" picture Url Domain 2 " ĊĊĠĠĠ Ġprivate Ġval Ġcharacter Database Model List Ġ= ĠlistOf ( ĊĠĠĠĠĠĠĠ ĠCharacter ListItem DB Model ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġid Ġ= Ġid Domain 1 , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġname Ġ= Ġname Domain 1 , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġdescription Ġ= Ġdescription Domain 1 , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġpicture Url Ġ= Ġpicture Url Domain 1 ĊĠĠĠĠĠĠĠ Ġ), ĊĠĠĠĠĠĠĠ ĠCharacter ListItem DB Model ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġid Ġ= Ġid Domain 2 , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġname Ġ= Ġname Domain 2 , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġdescription Ġ= Ġdescription Domain 2 , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġpicture Url Ġ= Ġpicture Url Domain 2 ĊĠĠĠĠĠĠĠ Ġ) ĊĠĠĠ Ġ) Ċ } Ċ