package Ġorg . opp ia . android . domain . audio Ċ Ċ import Ġandroid . app . Application Ċ import Ġandroid . content . Context Ċ import Ġandroid . net . Uri Ċ import Ġandroidx . lifecycle . Observer Ċ import Ġandroidx . test . core . app . Application Provider Ċ import Ġandroidx . test . ext . junit . runners . Android JUnit 4 Ċ import Ġcom . google . common . truth . Truth . assertThat Ċ import Ġdagger . Bind s Instance Ċ import Ġdagger . Component Ċ import Ġdagger . Module Ċ import Ġdagger . Provides Ċ import Ġorg . junit . Before Ċ import Ġorg . junit . Rule Ċ import Ġorg . junit . Test Ċ import Ġorg . junit . runner . RunWith Ċ import Ġorg . mockito . Argument Captor Ċ import Ġorg . mockito . Captor Ċ import Ġorg . mockito . Mock Ċ import Ġorg . mockito . Mockito . at Least Once Ċ import Ġorg . mockito . Mockito . verify Ċ import Ġorg . mockito . junit . Mockito JUnit Ċ import Ġorg . mockito . junit . Mockito Rule Ċ import Ġorg . opp ia . android . domain . audio . Audio Player Controller . Play Progress Ċ import Ġorg . opp ia . android . domain . audio . Audio Player Controller . Play Status Ċ import Ġorg . opp ia . android . domain . opp ialog ger . Log Storage Module Ċ import Ġorg . opp ia . android . testing . Fake Exception Logger Ċ import Ġorg . opp ia . android . testing . Test Coroutine Dispatch ers Ċ import Ġorg . opp ia . android . testing . Test Dispatcher Module Ċ import Ġorg . opp ia . android . testing . Test Log Reporting Module Ċ import Ġorg . opp ia . android . util . caching . Cache Assets Loc ally Ċ import Ġorg . opp ia . android . util . data . AsyncResult Ċ import Ġorg . opp ia . android . util . logging . Enable Console Log Ċ import Ġorg . opp ia . android . util . logging . Enable File Log Ċ import Ġorg . opp ia . android . util . logging . Global LogLevel Ċ import Ġorg . opp ia . android . util . logging . LogLevel Ċ import Ġorg . ro bo lectric . Shadow s Ċ import Ġorg . ro bo lectric . annotation . Config Ċ import Ġorg . ro bo lectric . annotation . Looper Mode Ċ import Ġorg . ro bo lectric . shadow s . Shadow MediaPlayer Ċ import Ġorg . ro bo lectric . shadow s . util . DataSource Ċ import Ġjava . io . IOException Ċ import Ġjavax . inject . Inject Ċ import Ġjavax . inject . Singleton Ċ import Ġkotlin . reflect . K Class Ċ import Ġkotlin . reflect . full . cast Ċ import Ġkotlin . test . fail Ċ Ċ /** ĠTests Ġfor Ġ[ Audio Player Controller Test ]. Ġ*/ Ċ @ RunWith ( Android JUnit 4 :: class ) Ċ @ Looper Mode ( Looper Mode . Mode . PA USED ) Ċ @ Config ( manifest Ġ= ĠConfig . NONE ) Ċ class ĠAudio Player Controller Test Ġ{ ĊĊĠ Ġ@ Rule ĊĠ Ġ@ Jvm Field ĊĠ Ġval Ġmock ito Rule : ĠMockito Rule Ġ= ĠMockito JUnit . rule () ĊĊĠ Ġ@ Mock ĊĠ Ġlateinit Ġvar Ġmock Audio Player Observer : ĠObserver < AsyncResult < Play Progress >> ĊĊĠ Ġ@ Captor ĊĠ Ġlateinit Ġvar Ġaudio Player Result Captor : ĊĠĠĠ ĠArgument Captor < AsyncResult < Play Progress >> ĊĊĠ Ġ@ Inject ĊĠ Ġlateinit Ġvar Ġcontext : ĠContext ĊĊĠ Ġ@ Inject ĊĠ Ġlateinit Ġvar Ġaudio Player Controller : ĠAudio Player Controller ĊĊĠ Ġ@ Inject ĊĠ Ġlateinit Ġvar Ġfake Exception Logger : ĠFake Exception Logger ĊĊĠ Ġ@ Inject ĊĠ Ġlateinit Ġvar Ġtest Coroutine Dispatch ers : ĠTest Coroutine Dispatch ers ĊĊĠ Ġprivate Ġlateinit Ġvar Ġshadow MediaPlayer : ĠShadow MediaPlayer ĊĊĠ Ġprivate Ġval ĠTEST _ URL Ġ= Ġ" https :// www . sound helix . com / examples / mp 3 / Sound Hel ix - Song - 1 . mp 3 " ĊĠ Ġprivate Ġval ĠTEST _ URL 2 Ġ= Ġ" https :// www . sound helix . com / examples / mp 3 / Sound Hel ix - Song - 2 . mp 3 " ĊĠ Ġprivate Ġval ĠTEST _ FAIL _ URL Ġ= Ġ" https :// www . sound helix . com / examples / mp 3 / Sound Hel ix - Song - 2 " ĊĊĠ Ġ@ Before ĊĠ Ġfun ĠsetUp () Ġ{ ĊĠĠĠ ĠsetUp Test Application Component () ĊĠĠĠ Ġadd Media Info () ĊĠĠĠ Ġshadow MediaPlayer Ġ= ĠShadow s . shadow Of ( audio Player Controller . getTest MediaPlayer ()) ĊĠĠĠ Ġshadow MediaPlayer . dataSource Ġ= ĠDataSource . to DataSource ( context , ĠUri . parse ( TEST _ URL )) ĊĠ Ġ} ĊĊĠ Ġ@ Test ĊĠ Ġfun Ġtest Controller _ initialize Player _ invoke Prepared _ reports Successful Init () Ġ{ ĊĠĠĠ Ġaudio Player Controller . initialize MediaPlayer () ĊĠĠĠ Ġaudio Player Controller . change DataSource ( TEST _ URL ) ĊĊĠĠĠ Ġshadow MediaPlayer . invoke Prepared Listener () ĊĊĠĠĠ ĠassertThat ( shadow MediaPlayer . is Prepared ). isTrue () ĊĠĠĠ ĠassertThat ( shadow MediaPlayer . is Re ally Playing ). isFalse () ĊĠ Ġ} ĊĊĠ Ġ@ Test ĊĠ Ġfun Ġtest Controller _ prepare Player _ invoke Play _ check Is Playing () Ġ{ ĊĠĠĠ Ġarrange MediaPlayer () ĊĊĠĠĠ Ġaudio Player Controller . play () ĊĊĠĠĠ ĠassertThat ( shadow MediaPlayer . is Re ally Playing ). isTrue () ĊĠ Ġ} ĊĊĠ Ġ@ Test ĊĠ Ġfun Ġtest Controller _ prepare Player _ invoke Pause _ check Not Is Playing () Ġ{ ĊĠĠĠ Ġarrange MediaPlayer () ĊĊĠĠĠ Ġaudio Player Controller . pause () ĊĊĠĠĠ ĠassertThat ( shadow MediaPlayer . is Re ally Playing ). isFalse () ĊĠ Ġ} ĊĊĠ Ġ@ Test ĊĠ Ġfun Ġtest Controller _ prepare Player _ invoke Seek To _ has Correct Progress () Ġ{ ĊĠĠĠ Ġarrange MediaPlayer () ĊĊĠĠĠ Ġaudio Player Controller . seek To ( 5 0 0 ) ĊĠĠĠ Ġtest Coroutine Dispatch ers . run Current () ĊĊĠĠĠ ĠassertThat ( shadow MediaPlayer . current Position Raw ). isEqualTo ( 5 0 0 ) ĊĠ Ġ} ĊĊĠ Ġ@ Test ĊĠ Ġfun Ġtest Controller _ prepare Player _ release MediaPlayer _ has End State () Ġ{ ĊĠĠĠ Ġarrange MediaPlayer () ĊĊĠĠĠ Ġaudio Player Controller . release MediaPlayer () ĊĊĠĠĠ ĠassertThat ( shadow MediaPlayer . state ). isEqualTo ( Shadow MediaPlayer . State . END ) ĊĠ Ġ} ĊĊĠ Ġ@ Test ĊĠ Ġfun Ġtest Controller _ prepare Player _ invoke Prepare _ capt ures Prepared State () Ġ{ ĊĠĠĠ Ġarrange MediaPlayer () ĊĊĠĠĠ Ġverify ( mock Audio Player Observer , Ġat Least Once ()). on Changed ( audio Player Result Captor . capture ()) ĊĠĠĠ ĠassertThat ( audio Player Result Captor . value . is Success ()). isTrue () ĊĠĠĠ ĠassertThat ( audio Player Result Captor . value . get OrThrow (). type ). isEqualTo ( Play Status . PRE PARE D ) ĊĠ Ġ} ĊĊĠ Ġ@ Test ĊĠ Ġfun Ġtest Controller _ release Player _ initialize Player _ capt ures Pending State () Ġ{ ĊĠĠĠ Ġaudio Player Controller . initialize MediaPlayer () ĊĊĠĠĠ Ġaudio Player Controller . release MediaPlayer () ĊĠĠĠ Ġaudio Player Controller . initialize MediaPlayer (). observe Fore ver ( mock Audio Player Observer ) ĊĠĠĠ Ġaudio Player Controller . change DataSource ( TEST _ URL ) ĊĊĠĠĠ Ġverify ( mock Audio Player Observer , Ġat Least Once ()). on Changed ( audio Player Result Captor . capture ()) ĊĠĠĠ ĠassertThat ( audio Player Result Captor . value . is Pending ()). isTrue () ĊĠ Ġ} ĊĊĠ Ġ@ Test ĊĠ Ġfun Ġtes Observer _ prepare Player _ invoke Completion _ capt ures Completed State () Ġ{ ĊĠĠĠ Ġarrange MediaPlayer () ĊĊĠĠĠ Ġshadow MediaPlayer . invoke Completion Listener () ĊĊĠĠĠ Ġverify ( mock Audio Player Observer , Ġat Least Once ()). on Changed ( audio Player Result Captor . capture ()) ĊĠĠĠ ĠassertThat ( audio Player Result Captor . value . is Success ()). isTrue () ĊĠĠĠ ĠassertThat ( audio Player Result Captor . value . get OrThrow (). type ). isEqualTo ( Play Status . COMPLETED ) ĊĠĠĠ ĠassertThat ( audio Player Result Captor . value . get OrThrow (). position ). isEqualTo ( 0 ) ĊĠ Ġ} ĊĊĠ Ġ@ Test ĊĠ Ġfun Ġtest Observer _ prepare Player _ invoke Change DataSource _ capt ures Pending State () Ġ{ ĊĠĠĠ Ġarrange MediaPlayer () ĊĊĠĠĠ Ġaudio Player Controller . change DataSource ( TEST _ URL 2 ) ĊĊĠĠĠ Ġverify ( mock Audio Player Observer , Ġat Least Once ()). on Changed ( audio Player Result Captor . capture ()) ĊĠĠĠ ĠassertThat ( audio Player Result Captor . value . is Pending ()). isTrue () ĊĠ Ġ} ĊĊĠ Ġ@ Test ĊĠ Ġfun Ġtest Observer _ prepare Player _ invoke Change DataSource After Play _ capt ures Pending State () Ġ{ ĊĠĠĠ Ġarrange MediaPlayer () ĊĊĠĠĠ Ġaudio Player Controller . play () ĊĠĠĠ Ġaudio Player Controller . change DataSource ( TEST _ URL 2 ) ĊĊĠĠĠ Ġverify ( mock Audio Player Observer , Ġat Least Once ()). on Changed ( audio Player Result Captor . capture ()) ĊĠĠĠ ĠassertThat ( audio Player Result Captor . value . is Pending ()). isTrue () ĊĠ Ġ} ĊĊĠ Ġ@ Test ĊĠ Ġfun Ġtest Observer _ prepare Player _ invoke Play _ capt ures Playing State () Ġ{ ĊĠĠĠ Ġarrange MediaPlayer () ĊĊĠĠĠ Ġaudio Player Controller . play () ĊĠĠĠ Ġtest Coroutine Dispatch ers . run Current () ĊĊĠĠĠ Ġverify ( mock Audio Player Observer , Ġat Least Once ()). on Changed ( audio Player Result Captor . capture ()) ĊĠĠĠ ĠassertThat ( audio Player Result Captor . value . is Success ()). isTrue () ĊĠĠĠ ĠassertThat ( audio Player Result Captor . value . get OrThrow (). type ). isEqualTo ( Play Status . PLAY ING ) ĊĠ Ġ} ĊĊĠ Ġ@ Test ĊĠ Ġfun Ġtest Observer _ prepare Player _ invoke Play And Advance _ capt ures Many Playing States () Ġ{ ĊĠĠĠ Ġarrange MediaPlayer () ĊĊĠĠĠ Ġ// ĠWait Ġfor Ġ 1 Ġsecond Ġfor Ġthe Ġplayer Ġto Ġenter Ġa Ġplaying Ġstate , Ġthen Ġfor c ibly Ġtrigger Ġcompletion . ĊĠĠĠ Ġaudio Player Controller . play () ĊĠĠĠ Ġtest Coroutine Dispatch ers . advance Time By ( 1 0 0 0 ) ĊĠĠĠ Ġshadow MediaPlayer . invoke Completion Listener () ĊĊĠĠĠ Ġverify ( mock Audio Player Observer , Ġat Least Once ()). on Changed ( audio Player Result Captor . capture ()) ĊĠĠĠ Ġval Ġresults Ġ= Ġaudio Player Result Captor . all Values ĊĠĠĠ Ġval Ġpending Index Ġ= Ġresults . indexOf Last Ġ{ Ġit . is Pending () Ġ} ĊĠĠĠ Ġval Ġprepared Index Ġ= Ġresults . indexOf Last Ġ{ Ġit . has Status ( Play Status . PRE PARE D ) Ġ} ĊĠĠĠ Ġval Ġplaying Index Ġ= Ġresults . indexOf Last Ġ{ Ġit . has Status ( Play Status . PLAY ING ) Ġ} ĊĠĠĠ Ġval Ġcompleted Index Ġ= Ġresults . indexOf Last Ġ{ Ġit . has Status ( Play Status . COMPLETED ) Ġ} ĊĠĠĠ Ġ// ĠVerify Ġthat Ġthere Ġare Ġat Ġleast Ġ 4 Ġstatuses : Ġpending , Ġprepared , Ġplaying , Ġand Ġcompleted , Ġand Ġin ĊĠĠĠ Ġ// Ġthat Ġorder . ĊĠĠĠ ĠassertThat ( results . size ). is GreaterThan ( 4 ) ĊĠĠĠ ĠassertThat ( pending Index ). is LessThan ( prepared Index ) ĊĠĠĠ ĠassertThat ( prepared Index ). is LessThan ( playing Index ) ĊĠĠĠ ĠassertThat ( playing Index ). is LessThan ( completed Index ) ĊĠ Ġ} ĊĊĠ Ġ@ Test ĊĠ Ġfun Ġtest Observer _ prepare Player _ invoke Pause _ capt ures Paused State () Ġ{ ĊĠĠĠ Ġarrange MediaPlayer () ĊĊĠĠĠ Ġaudio Player Controller . play () ĊĠĠĠ Ġaudio Player Controller . pause () ĊĊĠĠĠ Ġverify ( mock Audio Player Observer , Ġat Least Once ()). on Changed ( audio Player Result Captor . capture ()) ĊĠĠĠ ĠassertThat ( audio Player Result Captor . value . is Success ()). isTrue () ĊĠĠĠ ĠassertThat ( audio Player Result Captor . value . get OrThrow (). type ). isEqualTo ( Play Status . PA USED ) ĊĠ Ġ} ĊĊĠ Ġ@ Test ĊĠ Ġfun Ġtest Observer _ prepare Player _ invoke Prepared _ capt ures Correct Position () Ġ{ ĊĠĠĠ Ġarrange MediaPlayer () ĊĊĠĠĠ Ġverify ( mock Audio Player Observer , Ġat Least Once ()). on Changed ( audio Player Result Captor . capture ()) ĊĠĠĠ ĠassertThat ( audio Player Result Captor . value . get OrThrow (). position ). isEqualTo ( 0 ) ĊĠ Ġ} ĊĊĠ Ġ@ Test ĊĠ Ġfun Ġtest Observer _ prepare Player _ invoke Seek To _ capt ures Correct Position () Ġ{ ĊĠĠĠ Ġarrange MediaPlayer () ĊĊĠĠĠ Ġaudio Player Controller . seek To ( 5 0 0 ) ĊĠĠĠ Ġtest Coroutine Dispatch ers . run Current () ĊĠĠĠ Ġaudio Player Controller . play () ĊĠĠĠ Ġtest Coroutine Dispatch ers . run Current () ĊĊĠĠĠ Ġverify ( mock Audio Player Observer , Ġat Least Once ()). on Changed ( audio Player Result Captor . capture ()) ĊĠĠĠ ĠassertThat ( audio Player Result Captor . value . get OrThrow (). position ). isEqualTo ( 5 0 0 ) ĊĠ Ġ} ĊĊĠ Ġ@ Test ĊĠ Ġfun Ġtest Observer _ prepare Player _ invoke Play _ capt ures Correct Duration () Ġ{ ĊĠĠĠ Ġarrange MediaPlayer () ĊĊĠĠĠ Ġaudio Player Controller . play () ĊĊĠĠĠ Ġverify ( mock Audio Player Observer , Ġat Least Once ()). on Changed ( audio Player Result Captor . capture ()) ĊĠĠĠ ĠassertThat ( audio Player Result Captor . value . get OrThrow (). duration ). isEqualTo ( 2 0 0 0 ) ĊĠ Ġ} ĊĊĠ Ġ@ Test ĊĠ Ġfun Ġtest Observer _ prepare Player _ invoke Change DataSource _ capt ures Correct Position () Ġ{ ĊĠĠĠ Ġarrange MediaPlayer () ĊĊĠĠĠ Ġaudio Player Controller . seek To ( 5 0 0 ) ĊĠĠĠ Ġaudio Player Controller . change DataSource ( TEST _ URL 2 ) ĊĠĠĠ Ġshadow MediaPlayer . invoke Prepared Listener () ĊĠĠĠ Ġaudio Player Controller . play () ĊĊĠĠĠ Ġverify ( mock Audio Player Observer , Ġat Least Once ()). on Changed ( audio Player Result Captor . capture ()) ĊĠĠĠ ĠassertThat ( audio Player Result Captor . value . get OrThrow (). position ). isEqualTo ( 0 ) ĊĠ Ġ} ĊĊĠ Ġ@ Test ĊĠ Ġfun Ġtest Observer _ observe Init Player _ release Player _ init Player _ check No New Updates () Ġ{ ĊĠĠĠ Ġarrange MediaPlayer () ĊĊĠĠĠ Ġaudio Player Controller . release MediaPlayer () ĊĠĠĠ Ġaudio Player Controller . initialize MediaPlayer () ĊĊĠĠĠ Ġverify ( mock Audio Player Observer , Ġat Least Once ()). on Changed ( audio Player Result Captor . capture ()) ĊĠĠĠ Ġ// ĠIf Ġthe Ġobserver Ġwas Ġstill Ġgetting Ġupdates , Ġthe Ġresult Ġwould Ġbe Ġpending ĊĠĠĠ ĠassertThat ( audio Player Result Captor . value . is Success ()). isTrue () ĊĠĠĠ ĠassertThat ( audio Player Result Captor . value . get OrThrow (). type ). isEqualTo ( Play Status . PRE PARE D ) ĊĠ Ġ} ĊĊĠ Ġ@ Test ĊĠ Ġfun Ġtest Scheduling _ prepare Player _ invoke Pause And Advance _ verify Test DoesNot Hang () Ġ{ ĊĠĠĠ Ġarrange MediaPlayer () ĊĊĠĠĠ Ġaudio Player Controller . play () ĊĠĠĠ Ġtest Coroutine Dispatch ers . advance Time By ( 5 0 0 ) Ġ// ĠPlay Ġpart Ġof Ġthe Ġaudio Ġtrack Ġbefore Ġpa using . ĊĠĠĠ Ġaudio Player Controller . pause () ĊĠĠĠ Ġtest Coroutine Dispatch ers . advance Time By ( 2 0 0 0 ) ĊĊĠĠĠ Ġverify ( mock Audio Player Observer , Ġat Least Once ()). on Changed ( audio Player Result Captor . capture ()) ĊĠĠĠ ĠassertThat ( audio Player Result Captor . value . get OrThrow (). type ). isEqualTo ( Play Status . PA USED ) ĊĠĠĠ Ġ// ĠVerify : ĠIf Ġthe Ġtest Ġdoes Ġnot Ġhang , Ġthe Ġbehavior Ġis Ġcorrect . ĊĠ Ġ} ĊĊĠ Ġ@ Test ĊĠ Ġfun Ġtest Scheduling _ prepare Player _ invoke Completion And Advance _ verify Test DoesNot Hang () Ġ{ ĊĠĠĠ Ġarrange MediaPlayer () ĊĊĠĠĠ Ġaudio Player Controller . play () ĊĠĠĠ Ġtest Coroutine Dispatch ers . advance Time By ( 2 0 0 0 ) ĊĠĠĠ Ġshadow MediaPlayer . invoke Completion Listener () ĊĠĠĠ Ġtest Coroutine Dispatch ers . advance Time By ( 2 0 0 0 ) ĊĊĠĠĠ Ġverify ( mock Audio Player Observer , Ġat Least Once ()). on Changed ( audio Player Result Captor . capture ()) ĊĠĠĠ ĠassertThat ( audio Player Result Captor . value . get OrThrow (). type ). isEqualTo ( Play Status . COMPLETED ) ĊĠĠĠ Ġ// ĠVerify : ĠIf Ġthe Ġtest Ġdoes Ġnot Ġhang , Ġthe Ġbehavior Ġis Ġcorrect . ĊĠ Ġ} ĊĊĠ Ġ@ Test ĊĠ Ġfun Ġtest Scheduling _ observe Data _ remove Observer _ verify Test DoesNot Hang () Ġ{ ĊĠĠĠ Ġval Ġplay Progress Ġ= Ġaudio Player Controller . initialize MediaPlayer () ĊĠĠĠ Ġaudio Player Controller . change DataSource ( TEST _ URL ) ĊĠĠĠ Ġtest Coroutine Dispatch ers . run Current () ĊĊĠĠĠ Ġplay Progress . observe Fore ver ( mock Audio Player Observer ) ĊĠĠĠ Ġaudio Player Controller . play () ĊĠĠĠ Ġtest Coroutine Dispatch ers . advance Time By ( 2 0 0 0 ) ĊĠĠĠ Ġplay Progress . remove Observer ( mock Audio Player Observer ) ĊĊĠĠĠ Ġ// ĠVerify : ĠIf Ġthe Ġtest Ġdoes Ġnot Ġhang , Ġthe Ġbehavior Ġis Ġcorrect . ĊĠ Ġ} ĊĊĠ Ġ@ Test ĊĠ Ġfun Ġtest Scheduling _ add And Remove Observer s _ verify Test DoesNot Hang () Ġ{ ĊĠĠĠ Ġval Ġplay Progress Ġ= ĊĠĠĠĠĠ Ġaudio Player Controller . initialize MediaPlayer () ĊĠĠĠ Ġaudio Player Controller . change DataSource ( TEST _ URL ) ĊĠĠĠ Ġtest Coroutine Dispatch ers . run Current () ĊĊĠĠĠ Ġaudio Player Controller . play () ĊĠĠĠ Ġtest Coroutine Dispatch ers . advance Time By ( 2 0 0 0 ) ĊĠĠĠ Ġplay Progress . observe Fore ver ( mock Audio Player Observer ) ĊĠĠĠ Ġaudio Player Controller . pause () ĊĠĠĠ Ġplay Progress . remove Observer ( mock Audio Player Observer ) ĊĠĠĠ Ġaudio Player Controller . play () ĊĊĠĠĠ Ġ// ĠVerify : ĠIf Ġthe Ġtest Ġdoes Ġnot Ġhang , Ġthe Ġbehavior Ġis Ġcorrect . ĊĠ Ġ} ĊĊĠ Ġ@ Test ĊĠ Ġfun Ġtest Controller _ invoke Error Listener _ invoke Prepared _ verify Audio Status Is Failure () Ġ{ ĊĠĠĠ Ġaudio Player Controller . initialize MediaPlayer (). observe Fore ver ( mock Audio Player Observer ) ĊĠĠĠ Ġaudio Player Controller . change DataSource ( TEST _ URL ) ĊĊĠĠĠ Ġshadow MediaPlayer . invoke Error Listener (/* Ġwhat = Ġ*/ Ġ 0 , Ġ/* Ġextra = Ġ*/ Ġ 0 ) ĊĠĠĠ Ġshadow MediaPlayer . invoke Prepared Listener () ĊĊĠĠĠ Ġverify ( mock Audio Player Observer , Ġat Least Once ()). on Changed ( audio Player Result Captor . capture ()) ĊĠĠĠ ĠassertThat ( audio Player Result Captor . value . is Failure ()). isTrue () ĊĠ Ġ} ĊĊĠ Ġ@ Test ĊĠ Ġfun Ġtest Controller _ not Initialized _ release Player _ fails () Ġ{ ĊĠĠĠ Ġval Ġexception Ġ= ĠassertThrows ( IllegalStateException :: class ) Ġ{ ĊĠĠĠĠĠ Ġaudio Player Controller . release MediaPlayer () ĊĠĠĠ Ġ} ĊĊĠĠĠ ĠassertThat ( exception ). has Message That () ĊĠĠĠĠĠ Ġ. contains (" Media Ġplayer Ġhas Ġnot Ġbeen Ġpreviously Ġinitialized ") ĊĠ Ġ} ĊĊĠ Ġ@ Test ĊĠ Ġfun Ġtest Error _ not Prepared _ invoke Play _ fails () Ġ{ ĊĠĠĠ Ġval Ġexception Ġ= ĠassertThrows ( IllegalStateException :: class ) Ġ{ ĊĠĠĠĠĠ Ġaudio Player Controller . play () ĊĠĠĠ Ġ} ĊĊĠĠĠ ĠassertThat ( exception ). has Message That (). contains (" Media ĠPlayer Ġnot Ġin Ġa Ġprepared Ġstate ") ĊĠ Ġ} ĊĊĠ Ġ@ Test ĊĠ Ġfun Ġtest Error _ not Prepared _ invoke Pause _ fails () Ġ{ ĊĠĠĠ Ġval Ġexception Ġ= ĠassertThrows ( IllegalStateException :: class ) Ġ{ ĊĠĠĠĠĠ Ġaudio Player Controller . pause () ĊĠĠĠ Ġ} ĊĊĠĠĠ ĠassertThat ( exception ). has Message That (). contains (" Media ĠPlayer Ġnot Ġin Ġa Ġprepared Ġstate ") ĊĠ Ġ} ĊĊĠ Ġ@ Test ĊĠ Ġfun Ġtest Error _ not Prepared _ invoke Seek To _ fails () Ġ{ ĊĠĠĠ Ġval Ġexception Ġ= ĠassertThrows ( IllegalStateException :: class ) Ġ{ ĊĠĠĠĠĠ Ġaudio Player Controller . seek To ( 5 0 0 ) ĊĠĠĠ Ġ} ĊĊĠĠĠ ĠassertThat ( exception ). has Message That (). contains (" Media ĠPlayer Ġnot Ġin Ġa Ġprepared Ġstate ") ĊĠ Ġ} ĊĊĠ Ġ@ Test ĊĠ Ġfun Ġtest Controller _ initialize Player _ invoke Prepared _ reports failure _ logs Exception () Ġ{ ĊĠĠĠ Ġaudio Player Controller . initialize MediaPlayer () ĊĠĠĠ Ġaudio Player Controller . change DataSource ( TEST _ FAIL _ URL ) ĊĊĠĠĠ Ġshadow MediaPlayer . invoke Prepared Listener () ĊĠĠĠ Ġval Ġexception Ġ= Ġfake Exception Logger . get Most Recent Exception () ĊĊĠĠĠ ĠassertThat ( exception ). isInstanceOf ( IOException :: class . java ) ĊĠĠĠ ĠassertThat ( exception ). has Message That (). contains (" Invalid ĠURL ") ĊĠ Ġ} ĊĊĠ Ġprivate Ġfun Ġarrange MediaPlayer () Ġ{ ĊĠĠĠ Ġaudio Player Controller . initialize MediaPlayer (). observe Fore ver ( mock Audio Player Observer ) ĊĠĠĠ Ġaudio Player Controller . change DataSource ( TEST _ URL ) ĊĠĠĠ Ġshadow MediaPlayer . invoke Prepared Listener () ĊĠĠĠ Ġtest Coroutine Dispatch ers . run Current () ĊĠ Ġ} ĊĊĠ Ġprivate Ġfun Ġadd Media Info () Ġ{ ĊĠĠĠ Ġval ĠdataSource Ġ= ĠDataSource . to DataSource ( context , ĠUri . parse ( TEST _ URL )) ĊĠĠĠ Ġval ĠdataSource 2 Ġ= ĠDataSource . to DataSource ( context , ĠUri . parse ( TEST _ URL 2 )) ĊĠĠĠ Ġval ĠdataSource 3 Ġ= ĠDataSource . to DataSource ( context , ĠUri . parse ( TEST _ FAIL _ URL )) ĊĠĠĠ Ġval Ġmedia Info Ġ= ĠShadow MediaPlayer . Media Info ( ĊĠĠĠĠĠ Ġ/* Ġduration = Ġ*/ Ġ 2 0 0 0 , ĊĠĠĠĠĠ Ġ/* Ġpreparation Delay = Ġ*/ Ġ 0 ĊĠĠĠ Ġ) ĊĠĠĠ ĠShadow MediaPlayer . add Media Info ( dataSource , Ġmedia Info ) ĊĠĠĠ ĠShadow MediaPlayer . add Media Info ( dataSource 2 , Ġmedia Info ) ĊĠĠĠ ĠShadow MediaPlayer . add Exception ( dataSource 3 , ĠIOException (" Invalid ĠURL ")) ĊĠ Ġ} ĊĊĠ Ġ// ĠTODO (# 8 9 ): ĠMove Ġto Ġa Ġcommon Ġtest Ġlibrary . ĊĠ Ġprivate Ġfun Ġ< T Ġ: ĠThrowable > ĠassertThrows ( type : ĠK Class < T >, Ġoperation : Ġ() Ġ-> ĠUnit ): ĠT Ġ{ ĊĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠ Ġoperation () ĊĠĠĠĠĠ Ġfail (" Expected Ġto Ġencounter Ġexception Ġof Ġ$ type ") ĊĠĠĠ Ġ} Ġcatch Ġ( t : ĠThrowable ) Ġ{ ĊĠĠĠĠĠ Ġif Ġ( type . is Instance ( t )) Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġtype . cast ( t ) ĊĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġ// ĠUnexpected Ġexception ; Ġthrow Ġit . ĊĠĠĠĠĠ Ġthrow Ġt ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġprivate Ġfun ĠAsync Result < Play Progress >. has Status ( play Status : ĠPlay Status ): ĠBoolean Ġ{ ĊĠĠĠ Ġreturn Ġis Completed () Ġ&& Ġget OrThrow (). type Ġ== Ġplay Status ĊĠ Ġ} ĊĊĠ Ġprivate Ġfun ĠsetUp Test Application Component () Ġ{ ĊĠĠĠ ĠD agger Audio Player Controller Test _ Test Application Component . builder () ĊĠĠĠĠĠ Ġ. set Application ( Application Provider . getApplicationContext ()) ĊĠĠĠĠĠ Ġ. build () ĊĠĠĠĠĠ Ġ. inject ( this ) ĊĠ Ġ} ĊĊĠ Ġ// ĠTODO (# 8 9 ): ĠMove Ġthis Ġto Ġa Ġcommon Ġtest Ġapplication Ġcomponent . ĊĠ Ġ@ Module ĊĠ Ġclass ĠTest Module Ġ{ ĊĠĠĠ Ġ@ Provides ĊĠĠĠ Ġ@ Singleton ĊĠĠĠ Ġfun Ġprovide Context ( application : ĠApplication ): ĠContext Ġ{ ĊĠĠĠĠĠ Ġreturn Ġapplication ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ// ĠTODO (# 5 9 ): ĠEither Ġisolate Ġthese Ġto Ġtheir Ġown Ġshared Ġtest Ġmodule , Ġor Ġuse Ġthe Ġreal Ġlogging ĊĠĠĠ Ġ// Ġmodule Ġin Ġtests Ġto Ġavoid Ġneeding Ġto Ġspecify Ġthese Ġsettings Ġfor Ġtests . ĊĠĠĠ Ġ@ Enable Console Log ĊĠĠĠ Ġ@ Provides ĊĠĠĠ Ġfun Ġprovide Enable Console Log (): ĠBoolean Ġ= Ġtrue ĊĊĠĠĠ Ġ@ Enable File Log ĊĠĠĠ Ġ@ Provides ĊĠĠĠ Ġfun Ġprovide Enable File Log (): ĠBoolean Ġ= Ġfalse ĊĊĠĠĠ Ġ@ Global LogLevel ĊĠĠĠ Ġ@ Provides ĊĠĠĠ Ġfun Ġprovide Global LogLevel (): ĠLogLevel Ġ= ĠLogLevel . VERBOSE ĊĊĠĠĠ Ġ@ Cache Assets Loc ally ĊĠĠĠ Ġ@ Provides ĊĠĠĠ Ġfun Ġprovide Cache Assets Loc ally (): ĠBoolean Ġ= Ġfalse ĊĠ Ġ} ĊĊĠ Ġ// ĠTODO (# 8 9 ): ĠMove Ġthis Ġto Ġa Ġcommon Ġtest Ġapplication Ġcomponent . ĊĠ Ġ@ Singleton ĊĠ Ġ@ Component ( ĊĠĠĠ Ġmodules Ġ= Ġ[ ĊĠĠĠĠĠ ĠTest Module :: class , ĠTest Log Reporting Module :: class , ĠLog Storage Module :: class , ĊĠĠĠĠĠ ĠTest Dispatcher Module :: class ĊĠĠĠ Ġ] ĊĠ Ġ) ĊĠ Ġinterface ĠTest Application Component Ġ{ ĊĠĠĠ Ġ@ Component . Builder ĊĠĠĠ Ġinterface ĠBuilder Ġ{ ĊĠĠĠĠĠ Ġ@ Bind s Instance ĊĠĠĠĠĠ Ġfun Ġset Application ( application : ĠApplication ): ĠBuilder ĊĠĠĠĠĠ Ġfun Ġbuild (): ĠTest Application Component ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġinject ( audio Player Controller Test : ĠAudio Player Controller Test ) ĊĠ Ġ} Ċ } Ċ