package Ġio . ple o . ant ae us . core . services Ċ Ċ import Ġio . mock k .* Ċ import Ġio . ple o . ant ae us . core . exceptions . Billing Not Scheduled Exception Ċ import Ġio . ple o . ant ae us . core . exceptions . Currency Mismatch Exception Ċ import Ġio . ple o . ant ae us . core . exceptions . Customer NotFoundException Ċ import Ġio . ple o . ant ae us . core . exceptions . Network Exception Ċ import Ġio . ple o . ant ae us . core . external . Payment Provider Ċ import Ġio . ple o . ant ae us . data . Ant ae us Dal Ċ import Ġio . ple o . ant ae us . models . Currency Ċ import Ġio . ple o . ant ae us . models . Invoice Ċ import Ġio . ple o . ant ae us . models . Invoice Status Ċ import Ġorg . junit . jupiter . api . Test Ċ import Ġorg . junit . jupiter . api . Assertions .* Ċ import Ġorg . junit . jupiter . api . assert Throws Ċ import Ġjava . math . BigDecimal Ċ import Ġjava . time . LocalDate Ċ import Ġjava . time . Zone Offset Ċ import Ġjava . util .* Ċ Ċ internal Ġclass ĠBilling Service Test Ġ{ ĊĠĠĠ Ġprivate Ġval Ġmoney 1 Ġ= Ġio . ple o . ant ae us . models . Money ( BigDecimal . valueOf ( 1 0 0 ), ĠCurrency . DK K ) ĊĊĠĠĠ Ġprivate Ġval Ġinvoice 1 Ġ= ĠInvoice ( 1 , Ġ 1 , Ġmoney 1 , ĠInvoice Status . PENDING ) ĊĠĠĠ Ġprivate Ġval Ġinvoice 2 Ġ= ĠInvoice ( 2 , Ġ 4 0 4 , Ġmoney 1 , ĠInvoice Status . PENDING ) ĊĠĠĠ Ġprivate Ġval Ġinvoice 3 Ġ= ĠInvoice ( 3 , Ġ 3 , Ġmoney 1 , ĠInvoice Status . PENDING ) ĊĠĠĠ Ġprivate Ġval Ġinvoice 4 Ġ= ĠInvoice ( 4 , Ġ 4 , Ġmoney 1 , ĠInvoice Status . PENDING ) ĊĠĠĠ Ġprivate Ġval Ġinvoice 5 Ġ= ĠInvoice ( 5 , Ġ 5 , Ġmoney 1 , ĠInvoice Status . PENDING ) ĊĊĠĠĠ Ġprivate Ġval Ġin voices Ġ= ĊĠĠĠĠĠĠĠ ĠlistOf ( invoice 1 , Ġinvoice 2 , Ġinvoice 3 , Ġinvoice 4 , Ġinvoice 5 ) ĊĊĠĠĠ Ġprivate Ġval Ġprocessed Invoice 1 Ġ= ĠInvoice ( 1 , Ġ 1 , Ġmoney 1 , ĠInvoice Status . PA ID ) ĊĠĠĠ Ġprivate Ġval Ġprocessed Invoice 2 Ġ= ĠInvoice ( 2 , Ġ 4 0 4 , Ġmoney 1 , ĠInvoice Status . CUSTOMER _ NOT _ FOUND ) ĊĠĠĠ Ġprivate Ġval Ġprocessed Invoice 3 Ġ= ĠInvoice ( 3 , Ġ 3 , Ġmoney 1 , ĠInvoice Status . CUR RE NCY _ MIS MATCH ) ĊĠĠĠ Ġprivate Ġval Ġprocessed Invoice 4 Ġ= ĠInvoice ( 4 , Ġ 4 , Ġmoney 1 , ĠInvoice Status . NETWORK _ EXCEPTION ) ĊĠĠĠ Ġprivate Ġval Ġprocessed Invoice 5 Ġ= ĠInvoice ( 5 , Ġ 5 , Ġmoney 1 , ĠInvoice Status . IN SUFF IC IENT _ BAL ANCE ) ĊĊĠĠĠ Ġprivate Ġval Ġprocessed In voices List Ġ= ĊĠĠĠĠĠĠĠ ĠlistOf ( processed Invoice 1 , Ġprocessed Invoice 2 , Ġprocessed Invoice 3 , Ġprocessed Invoice 4 , Ġprocessed Invoice 5 ) ĊĊĠĠĠ Ġprivate Ġval Ġdate : ĠLocalDate Ġ= ĠLocalDate . of ( 2 0 2 1 , Ġ 1 2 , Ġ 1 ) ĊĠĠĠ Ġprivate Ġval Ġexpected Date : ĠDate Ġ= ĠDate . from ( LocalDate . of ( 2 0 2 2 , Ġ 1 , Ġ 1 ). at Start OfDay (). to Instant ( Zone Offset . UTC )) ĊĠĠĠ Ġprivate Ġval Ġpast Date : ĠLocalDate Ġ= ĠLocalDate . of ( 2 0 1 1 , Ġ 1 2 , Ġ 1 ) ĊĊĠĠĠ Ġprivate Ġval Ġdal Ġ= Ġmock k < Ant ae us Dal > Ġ{ ĊĠĠĠĠĠĠĠ Ġevery Ġ{ Ġfetch Pending In voices () Ġ} Ġreturns Ġin voices ĊĠĠĠĠĠĠĠ Ġevery Ġ{ Ġupdate Invoice ( processed Invoice 1 ) Ġ} Ġreturns Ġ 1 ĊĠĠĠĠĠĠĠ Ġevery Ġ{ Ġupdate Invoice ( processed Invoice 2 ) Ġ} Ġreturns Ġ 4 0 4 ĊĠĠĠĠĠĠĠ Ġevery Ġ{ Ġupdate Invoice ( processed Invoice 3 ) Ġ} Ġreturns Ġ 3 ĊĠĠĠĠĠĠĠ Ġevery Ġ{ Ġupdate Invoice ( processed Invoice 4 ) Ġ} Ġreturns Ġ 4 ĊĠĠĠĠĠĠĠ Ġevery Ġ{ Ġupdate Invoice ( processed Invoice 5 ) Ġ} Ġreturns Ġ 5 ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġval Ġpayment Provider Ġ= Ġmock k < Payment Provider > Ġ{ ĊĠĠĠĠĠĠĠ Ġevery Ġ{ Ġcharge ( invoice 1 ) Ġ} Ġreturns Ġtrue ĊĠĠĠĠĠĠĠ Ġevery Ġ{ Ġcharge ( invoice 2 ) Ġ} Ġthrows ĠCustomer NotFoundException ( invoice 2 . customer Id ) ĊĠĠĠĠĠĠĠ Ġevery Ġ{ Ġcharge ( invoice 3 ) Ġ} Ġthrows ĠCurrency Mismatch Exception ( invoice 3 . id , Ġinvoice 3 . customer Id ) ĊĠĠĠĠĠĠĠ Ġevery Ġ{ Ġcharge ( invoice 4 ) Ġ} Ġthrows ĠNetwork Exception () ĊĠĠĠĠĠĠĠ Ġevery Ġ{ Ġcharge ( invoice 5 ) Ġ} Ġreturns Ġfalse ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġval Ġbilling Service Ġ= ĠBilling Service ( dal Ġ= Ġdal , Ġpayment Provider Ġ= Ġpayment Provider ) ĊĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġ` will Ġcorrectly Ġroll Ġover Ġmonth Ġand Ġadd Ġyear Ġif Ġit Ġis Ġde cember `() Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġresult Ġ= Ġbilling Service . schedule Billing ( date ) ĊĠĠĠĠĠĠĠ ĠassertEquals ( expected Date , Ġresult ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġ` will Ġreturn Ġthe Ġlist Ġof Ġcorrectly Ġprocessed Ġin voices `() Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġresult Ġ= Ġbilling Service . process Pending In voices ( invoices ) ĊĠĠĠĠĠĠĠ ĠassertTrue ( result . contains All ( processed In voices List )) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġ` will Ġreturn Ġthe Ġcorrect Ġdate Ġstring `() Ġ{ ĊĠĠĠĠĠĠĠ Ġbilling Service . schedule Billing ( date ) ĊĠĠĠĠĠĠĠ Ġval Ġresult Ġ= Ġbilling Service . getNext Billing Date () ĊĠĠĠĠĠĠĠ ĠassertEquals ( expected Date , Ġresult ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġ` will Ġthrow Ġif Ġno Ġbilling Ġscheduled `() Ġ{ ĊĠĠĠĠĠĠĠ ĠassertThrows < Billing Not Scheduled Exception > Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbilling Service . getNext Billing Date () ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġ` will Ġthrow Ġif Ġscheduled Ġbilling Ġhas Ġbeen Ġrun `() Ġ{ ĊĠĠĠĠĠĠĠ Ġbilling Service . schedule Billing ( past Date ) ĊĠĠĠĠĠĠĠ Ġ// ĠWait Ġfor Ġthe Ġscheduled Ġtask Ġto Ġbe Ġrun ĊĠĠĠĠĠĠĠ ĠThread . sleep ( 1 0 0 0 ) ĊĠĠĠĠĠĠĠ ĠassertThrows < Billing Not Scheduled Exception > Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbilling Service . getNext Billing Date () ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġ` will Ġreturn Ġtrue Ġif Ġscheduled Ġtask Ġis Ġcancelled Ġsuccessfully `() Ġ{ ĊĠĠĠĠĠĠĠ Ġbilling Service . schedule Billing () ĊĠĠĠĠĠĠĠ Ġval Ġresult Ġ= Ġbilling Service . cancel () ĊĠĠĠĠĠĠĠ ĠassertTrue ( result ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġ` will Ġreturn Ġfalse Ġif Ġscheduled Ġtask Ġhas Ġalready Ġrun `() Ġ{ ĊĠĠĠĠĠĠĠ Ġbilling Service . schedule Billing ( past Date ) ĊĠĠĠĠĠĠĠ ĠThread . sleep ( 1 0 0 0 ) ĊĠĠĠĠĠĠĠ Ġval Ġresult Ġ= Ġbilling Service . cancel () ĊĠĠĠĠĠĠĠ ĠassertFalse ( result ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġ` will Ġsuccessfully Ġre schedule Ġtask Ġafter Ġcancel ing `() Ġ{ ĊĠĠĠĠĠĠĠ Ġbilling Service . schedule Billing ( date ) ĊĠĠĠĠĠĠĠ Ġbilling Service . cancel () ĊĠĠĠĠĠĠĠ Ġval Ġresult Ġ= Ġbilling Service . schedule Billing ( date ) ĊĠĠĠĠĠĠĠ ĠassertEquals ( result , Ġexpected Date ) ĊĠĠĠ Ġ} Ċ }