diff --git a/docs/workshops/day_2_tdd.md b/docs/workshops/day_2_tdd.md
index 65f0a0e2f233f857bfb7f04cdc86505c19b10c28..85982839746c4e05e7c4c2ac66811856404b7d4b 100644
--- a/docs/workshops/day_2_tdd.md
+++ b/docs/workshops/day_2_tdd.md
@@ -1,22 +1,23 @@
 # Day 2: Test-Driven Development
 
-* Session 1: 9:00 - 10:00: [Testing Category][1]
-* Session 2: 10:15 - 11:30: Hands-on: A bigger Case study
-* Session 3: 13:30 - 15:00: Hands-on: A bigger Case study
+* Session 1: 9:00 - 10:30: [Testing Category][1]
+* Session 2: 10:30 - 11:15: Hands-on: A bigger Case study
+* Session 3: 13:00 - 15:30: Hands-on: A bigger Case study
 * Session 4: 15:30 - 16:30: Overview, Discussion, Lesson learned
 
 
 ## Dive Deeper into Unit Testing
 
 Pada hari pertama, telah disediakan contoh bagaimana membuat aplikasi web berbasis Spring Boot dengan *unit test* dan functional test suite yang lengkap.
-Pada hari ini, kita akan mendalami terkait bagaimana membuat *unit test suite* yang memenuhi 5 aspek FIRST principle, sembari mengikuti *flow* Test-Driven Development:
-- Fast: proses *testing* secara keseluruhan harus dilakukan dengan cepat.
-- Isolated: setiap *unit test* **tidak boleh memengaruhi hasil** *unit test* lain.
-- Repeatable: hasil tes konsisten meskipun dijalankan berkali-kali pada kondisi yang sama.
-- Self-Validating: bisa digunakan untuk mengecek kesesuaian aplikasi jika terjadi perubahan kode.
-- Thorough: sebisa mungkin mencakup keseluruhan kode dan *business logic* aplikasi.
-
-Untuk *hands-on* ini, kita akan fokus ke sisi back-end dari aplikasi.
+Pada hari ini, kita akan mendalami terkait bagaimana membuat *unit test suite* yang memenuhi 5 aspek FIRST *principle*:
+
+- ***Fast***: proses *testing* secara keseluruhan harus dilakukan dengan cepat.
+- ***Isolated***: setiap *unit test* **tidak boleh memengaruhi hasil** *unit test* lain.
+- ***Repeatable***: hasil tes konsisten meskipun dijalankan berkali-kali pada kondisi yang sama.
+- ***Self-Validating***: bisa digunakan untuk mengecek kesesuaian aplikasi jika terjadi perubahan kode.
+- ***Thorough***: sebisa mungkin mencakup keseluruhan kode dan *business logic* aplikasi.
+
+Untuk *hands-on* ini, kita akan fokus ke sisi *back-end* dari aplikasi.
 Kita akan memanfaatkan teknik berupa *mock* dan *stub* untuk membuat kode cakupan setiap *test* kita menjadi lebih fokus terhadap objek yang benar-benar akan di-*test*.
 
 **Apa itu *mock*?**
@@ -24,7 +25,7 @@ Kita akan memanfaatkan teknik berupa *mock* dan *stub* untuk membuat kode cakupa
 *Mock* adalah objek palsu yang kita bisa gunakan untuk menggunakan objek yang menjadi dependensi dari suatu fungsi/kelas.
 *Mock object* dapat kita gunakan untuk *tracking*, yaitu melihat bagaimana interaksi antara fungsi yang kita *test* dengan objek dependensi tersebut.
 
-Contoh sederhananya adalah, kita mau melihat apakah fungsi kita melakukan proses *Save Object* ke sebuah database.
+Contoh sederhananya adalah, kita ingin melihat apakah fungsi kita melakukan proses *Save Object* ke sebuah database.
 Berikut adalah contoh penggunaan *mock* di *test code*:
 ```java
     @InjectMocks
@@ -46,10 +47,10 @@ Berikut adalah contoh penggunaan *mock* di *test code*:
 *Stub* adalah objek palsu yang kita bisa gunakan untuk menyimulasikan keluaran fungsi-fungsi pada objek tersebut.
 Hal ini sangat berguna jika kita menggunakan *library* eksternal atau API eksternal,
 sehingga *unit test* kita tidak akan membuang waktu dan *resource* untuk mengakses *library* atau API tersebut.
-Kita bisa meminta *stub* untuk mengembalikan hasil yang kita mau untuk diproses oleh fungsi yang kita *test*.
+Kita bisa meminta *stub* untuk mengembalikan hasil yang kita inginkan untuk diproses oleh fungsi yang kita *test*.
 Kita juga bisa meminta *stub* untuk memberikan *error* untuk menyimulasikan *negative case*.
 
-Contoh sederhananya adalah, kita mau menyimulasikan bahwa terdapat objek *Payment* di database,
+Contoh sederhananya adalah, kita ingin menyimulasikan bahwa terdapat objek *Payment* di database,
 tanpa kita harus memasukkan entri *Payment* ke dalam database terlebih dahulu.
 Berikut adalah contoh penggunaan *stub* di *test code*:
 ```java
@@ -66,7 +67,7 @@ Berikut adalah contoh penggunaan *stub* di *test code*:
         Payment payment = new Payment("a-01", "Bambang", 20000);
         when(repository.getById("a-01")).thenReturn(payment);
 
-        // Cek apakakh eksekusi method "create" akan memunculkan exception PaymentAlreadyCreated
+        // Cek apakah eksekusi method "create" akan memunculkan exception PaymentAlreadyCreated
         assertThrows(PaymentAlreadyCreated.class, () -> {
             service.create("a-01", "Usep", 100000);
         });
@@ -78,10 +79,10 @@ Berikut adalah contoh penggunaan *stub* di *test code*:
 
 Untuk mengikuti rangkaian kegiatan workshop hari ini, harap persiapkan _tools_ berikut di komputer anda:
 
-- Git
-- IntelliJ Community Edition
-- Java JDK 17 (`java` dan `javac`)
-- Apache Maven (`mvn`)
+- [Git](https://git-scm.com/)
+- [Java JDK 17](https://adoptium.net/temurin/releases/?version=17) (`java` dan `javac`)
+- [IntelliJ IDEA Community Edition](https://www.jetbrains.com/idea/download/)
+- [Apache Maven](https://maven.apache.org/download.cgi) (`mvn`)
 
 Buat salinan _branch_ `main` dari repositori Git kode templat workshop hari ini:
 
@@ -104,26 +105,28 @@ Kita akan lengkapi bersama saat tutorial ini.
 
 ## SIBAYAR: Pembayaran peer-to-peer dengan mekanisme Accept Payment dan Disbursement
 
-SIBAYAR merupakan sistem pembayaran peer-to-peer sederhana yang menggunakan sebuah API *payment gateway* (dalam kasus ini, Flip) untuk menyalurkan uang.
+SIBAYAR merupakan sistem pembayaran peer-to-peer sederhana yang menggunakan sebuah API *payment gateway* (dalam kasus ini, [Flip][2]) untuk menyalurkan uang.
 Berikut adalah flow keseluruhan dari sistem SIBAYAR:
+
 1. User bisa melakukan transfer uang ke User lain, atau ke nomor rekening yang tidak terdaftar di SIBAYAR.
-2. SIBAYAR mengontak API Flip untuk mendapatkan link pembayaran,
+2. SIBAYAR mengontak API [Flip][2] untuk mendapatkan link pembayaran,
    yang bisa digunakan User untuk membayar transfer tersebut.
-3. User melakukan pembayaran menggunakan link pembayaran yang telah diberikan API Flip ke User melalui SIBAYAR.
+3. User melakukan pembayaran menggunakan link pembayaran yang telah diberikan API [Flip][2] ke User melalui SIBAYAR.
 4. Jika user sudah selesai melakukan pembayaran,
-   API Flip akan mengeksekusi *payment callback endpoint* milik SIBAYAR untuk melanjutkan proses transfer.
-5. Ketika API Flip mengeksekusi *payment callback endpoint* SIBAYAR,
+   API [Flip][2] akan mengeksekusi *payment callback endpoint* milik SIBAYAR untuk melanjutkan proses transfer.
+5. Ketika API [Flip][2] mengeksekusi *payment callback endpoint* SIBAYAR,
    sistem SIBAYAR akan kembali mengontak API Flip untuk transfer uang (*disbursement*) ke rekening tujuan.
-6. Ketika Flip berhasil melakukan *disbursement*,
+6. Ketika [Flip][2] berhasil melakukan *disbursement*,
    API Flip akan mengeksekusi *disbursement callback endpoint* milik SIBAYAR,
    sehingga pembayaran tersebut akan ditandai **sukses** oleh SIBAYAR.
 
-Untuk tutorial hari ini, tidak perlu khawatirkan akses *callback* dari Flip,
-karena Flip hanya bisa melakukan *callback* ketika aplikasi SIBAYAR sudah di-*deploy* secara publik.
+Untuk tutorial hari ini, tidak perlu khawatirkan akses *callback* dari [Flip][2],
+karena [Flip][2] hanya bisa melakukan *callback* ketika aplikasi SIBAYAR sudah di-*deploy* secara publik.
 Akan tetapi, kita tetap perlu mengimplementasikan keseluruhan sistem SIBAYAR, dengan menyusun tiga *controller*:
+
 1. `AuthenticationController`: untuk proses *login* dan *register* akun baru.
 2. `PaymentController`: untuk melakukan *payment* baru dan melihat histori *payment*.
-3. `CallbackController`: untuk *payment callback endpoint* dan *disbursement callback endpoint* yang akan dikontak oleh API Flip.
+3. `CallbackController`: untuk *payment callback endpoint* dan *disbursement callback endpoint* yang akan dikontak oleh API [Flip][2].
 
 ## Membuat *Test Suite Class*
 
@@ -132,14 +135,18 @@ Untuk proses pembuatan *unit test*, kita akan memanfaatkan library `Mockito`.
 Untuk menyusun *test suite* yang support `Mockito`,
 kita perlu tambahkan anotasi `@ExtendWith(MockitoExtension.class)`.
 
-Selain itu, kita perlu membuat fungsi yang akan dijalankan sebagai *set up* setiap *unit test* pada *test suite*.
-Fungsi `setUp()` akan dijalankan **sebelum** setiap *unit test* dijalankan.
-Dengan fungsi `setUp()`, kita bisa mengisolasi setiap *unit test* agar hasilnya bisa independen,
+Selain itu, kita perlu membuat fungsi `setUp()` dengan anotasi `@BeforeEach`, yang berfungsi sebagai prosedur *set up* untuk setiap *unit test* pada *test suite*.
+Fungsi `setUp()` yang dianotasi dengan `@BeforeEach` akan dijalankan **sebelum** setiap *unit test* dijalankan.
+Dengan fungsi `setUp()`, kita bisa mengisolasi proses inisiasi setiap *unit test* agar hasilnya bisa independen,
 selain itu juga meningkatkan *reusability* dan konsistensi antar *test case* karena menggunakan cara inisiasi yang serupa.
 
-Berikut adalah contoh inisiasi *test suite* untuk kelas `PaymentServiceImpl`.
-Buat sejajar dengan kelas aslinya, yaitu di *package* `com.example.sibayar.service.payment`:
+Berikut adalah contoh inisiasi *test suite* untuk *class* `PaymentServiceImpl`, yaitu *class* `PaymentServiceImplTest` yang dibuat di *folder* `src/test/com/example/sibayar/service/payment`:
+
 ```java
+package com.example.sibayar.service.payment;
+
+// ... import dependensi yang dibutuhkan untuk test
+
 @ExtendWith(MockitoExtension.class)
 class PaymentServiceImplTest {
 
@@ -161,73 +168,88 @@ class PaymentServiceImplTest {
     @BeforeEach
     void setUp() {
         paymentToOtherRequest = PaymentToOtherRequest.builder()
-                                                     .destinationName("Pak Bambang")
-                                                     .destinationBankCode("bca")
-                                                     .destinationAccountNumber("123456789")
-                                                     .amount(50000)
-                                                     .build();
+            .destinationName("Pak Bambang")
+            .destinationBankCode("bca")
+            .destinationAccountNumber("123456789")
+            .amount(50000)
+            .build();
         paymentToUserRequest = PaymentToUserRequest.builder()
-                                                   .destinationUserId(2)
-                                                   .amount(50000)
-                                                   .build();
+            .destinationUserId(2)
+            .amount(50000)
+            .build();
         paymentLinkResponse = PaymentLinkResponse.builder()
-                                                 .expiredDate(LocalDateTime.of(2023, 11, 4, 23, 59))
-                                                 .linkId(1)
-                                                 .linkUrl("https://flip.id/bambang")
-                                                 .build();
+            .expiredDate(LocalDateTime.of(2023, 11, 4, 23, 59))
+            .linkId(1)
+            .linkUrl("https://flip.id/bambang")
+            .build();
         payment = Payment.builder()
-                         .id(1)
-                         .sender(user)
-                         .destinationName("Pak Bambang")
-                         .destinationBankCode("bca")
-                         .destinationAccountNumber("123456789")
-                         .amount(50000)
-                         .paymentLinkId(1)
-                         .paymentLinkUrl("https://flip.id/bambang")
-                         .expiredDate(LocalDateTime.of(2023, 11, 4, 23, 59))
-                         .status(String.valueOf(PaymentStatus.WAITING_PAYMENT))
-                         .build();
+            .id(1)
+            .sender(user)
+            .destinationName("Pak Bambang")
+            .destinationBankCode("bca")
+            .destinationAccountNumber("123456789")
+            .amount(50000)
+            .paymentLinkId(1)
+            .paymentLinkUrl("https://flip.id/bambang")
+            .expiredDate(LocalDateTime.of(2023, 11, 4, 23, 59))
+            .status(String.valueOf(PaymentStatus.WAITING_PAYMENT))
+            .build();
     }
 }
 ```
 
 Dalam kasus ini, terdapat 3 objek yang akan dibuat objek *mock*/*stub*-nya, yang ditandai dengan anotasi `@Mock`:
-1. `PaymentRepository`: repositori untuk Payment, diperlukan untuk operasi *database* terkait entri `Payment`.
-2. `UserRepository`L repositori untuk Payment, diperlukan untuk operasi *database* terkait entri `User`.
-3. `User`: objek data User (pengguna).
+
+1. `PaymentRepository`: sebuah *class* yang bertugas untuk melakukan operasi *database* terhadap tabel `Payment`. Di Spring Boot, *class* ini disebut sebagai *repository*.
+2. `UserRepository`: sebuah *class* yang bertugas untuk melakukan operasi *database* terhadap tabel `User`. Di Spring Boot, *class* ini disebut sebagai *repository*.
+3. `User`: sebuah *class* yang bertugas sebagai *database model* untuk tabel User (pengguna).
 
 Ketiga objek ini kemudian akan di-*inject* ke `PaymentServiceImpl` yang akan kita test, ditandai dengan anotasi `@InjectMocks`.
 
-Terdapapt juga 2 objek yang akan menjadi parameter dari *fungsi* yang akan di-*test*, yaitu:
-1. `PaymentToUserRequest`: *Data Transfer Object* (DTO) sebagai *parameter* fungsi `payToUser`, yang datang dari `PaymentController`.
-2. `PaymentToOtherRequest`: *Data Transfer Object* (DTO) sebagai *parameter* fungsi `payToOtherDestination`, yang datang dari `PaymentController`.
+Terdapat juga 2 objek yang akan menjadi parameter dari *fungsi* yang akan di-*test*, yaitu:
+
+1. `PaymentToUserRequest`: sebuah *Data Transfer Object* (DTO) sebagai argumen dari fungsi `payToUser`, yang datang dari `PaymentController`.
+2. `PaymentToOtherRequest`: sebuah *Data Transfer Object* (DTO) sebagai argumen dari fungsi `payToOtherDestination`, yang datang dari `PaymentController`.
 
 Terdapat juga 2 objek yang akan menjadi hasil dari *stub*, yaitu:
-1. `Payment`: objek data Payment.
-2. `PaymentLinkResponse`: *Data Transfer Object* (DTO) untuk menampung hasil kembalian dari Flip API ketika membuat *payment link*.
 
-### Tugas Anda
-- [ ] Silakan *copy* snippet kode yang telah dijelaskan ke dalam project Anda.
+1. `Payment`: sebuah objek *database model* untuk tabel Payment.
+2. `PaymentLinkResponse`: sebuah objek *Data Transfer Object* (DTO) untuk menampung hasil kembalian dari Flip API ketika membuat *payment link*.
 
-### Latihan Mandiri: Inisiasi *test suite* `CallbackServiceImpl`
-- [ ] Buat *test suite* `CallbackServiceImpl`, sejajar dengan *test suite* `PaymentServiceImpl` yang telah dibuat.
-- [ ] *Test suite* terdiri dari objek *mock/stub* berikut:
-  1. `PaymentRepositoryImpl`
-- [ ] *Test suite* terdiri dari objek untuk parameter fungsi yang di-*test* berikut:
-  1. `PaymentCallbackRequest`
-  2. `DisbursementCallbackRequest`
-- [ ] *Test suite* terdiri dari objek *hasil stub* berikut:
-  1. `DisbursementResponse`
-- [ ] Buat fungsi `setUp()` untuk menyusun objek-objek *hasil stub*.
+### Tugas Anda
+- [ ] Buat *test suite* `PaymentServiceImplTest` sesuai dengan arahan yang diberikan.
+    - [ ] *Test suite* terdiri dari objek *mock/stub* berikut:
+        - `PaymentRepository`
+        - `UserRepository`
+        - `User`
+    - [ ] *Test suite* terdiri dari objek untuk parameter fungsi yang di-*test* berikut:
+        - `PaymentToUserRequest`
+        - `PaymentToOtherRequest`
+    - [ ] *Test suite* terdiri dari objek *hasil stub* berikut:
+        - `Payment`
+        - `PaymentLinkResponse`
+    - [ ] Buat fungsi `setUp()` untuk menyusun objek-objek *hasil stub*.
+
+### Latihan Mandiri: Inisiasi *test suite* `CallbackServiceImplTest`
+- [ ] Buat *test suite* `CallbackServiceImplTest`, sejajar dengan *test suite* `PaymentServiceImplTest` yang telah dibuat.
+    - [ ] *Test suite* terdiri dari objek *mock/stub* berikut:
+        - `PaymentRepository`
+    - [ ] *Test suite* terdiri dari objek untuk parameter fungsi yang di-*test* berikut:
+        - `PaymentCallbackRequest`
+        - `DisbursementCallbackRequest`
+    - [ ] *Test suite* terdiri dari objek *hasil stub* berikut:
+        - `Payment`
+        - `DisbursementResponse`
+    - [ ] Buat fungsi `setUp()` untuk menyusun objek-objek *hasil stub*.
 
 
 ## Melakukan *Mock* dan *Stub* untuk Akses Database dan Helper Function Lain
 
-SIBAYAR menggunakan Spring Data JPA untuk mengakases database In-Memory H2.
+SIBAYAR menggunakan Spring Data JPA untuk mengakses database In-Memory H2.
 Dalam menggunakan Spring Data JPA, kita perlu membuat *repository interface* yang berisikan daftar *method* untuk mengakses *database*.
 JPA kemudian akan membuatkan implementasi setiap *method* secara *on the fly* sesuai dengan nama *method* yang kita gunakan.
 *Repository interface* tersebut akan menjadi sebuah komponen Spring yang bisa digunakan untuk *service* yang akan kita buat bersama.
-Di tutorial hari ini, sudah tersedia *repository* untuk objek `Payment` dan objek `User`.
+Di tutorial hari ini, sudah tersedia *repository* untuk tabel *database* `Payment` yaitu `PaymentRepository`, dan tabel *database* `User` yaitu `UserRepository`.
 
 *Database* adalah komponen dependensi pada objek *service* yang perlu kita isolasi.
 *Programmer* pada umumnya akan membuat entri ke *database* lalu akan menghapusnya kembali ketika test selesai.
@@ -235,7 +257,7 @@ Akan tetapi, hal tersebut jadi memakan *resource* lebih dengan perlu adanya *tes
 Oleh karena itu, dalam menyusun *unit test* untuk *service*, kita perlu melakukan *mock* dan *stub* komponen *Repository*.
 Sebagai contoh, berikut adalah beberapa *test case* yang bisa Anda gunakan:
 
-### `payToUser` sukses menyimpan dan mengembalikan objek `Payment` baru
+### Contoh 1: Fungsi `payToUser` sukses menyimpan dan mengembalikan objek `Payment` baru
 ```java
     @Test
     void testPayToUserSuccess() {
@@ -253,14 +275,18 @@ Sebagai contoh, berikut adalah beberapa *test case* yang bisa Anda gunakan:
     }
 ```
 
-Terlihat bahwa terdapat *stubbing* untuk fungsi `userRepository.findById(Integer)` untuk menyimulasikan bahwa di database terdapat objek *mock* `user`.
-Selain itu, juga terdapat *stubbing* untuk fungsi `service.getPaymentLink(PaymentLinkRequest)` untuk mengembalikan objek `paymentLinkResponse`.
+Berikut adalah penjelasan terkait *test case* ini:
+
+1. Di line 3, terdapat *stubbing* untuk fungsi `userRepository.findById(Integer)` untuk menyimulasikan bahwa di database terdapat objek *mock* `user`.
+2. Di line 4, terdapat *stubbing* untuk fungsi `service.getPaymentLink(PaymentLinkRequest)` untuk mengembalikan objek `paymentLinkResponse`, untuk menyimulasikan kembalian dari pemanggilan API Flip untuk mendapatkan *payment link*.
+
 *Test case* ini akan mengecek:
-1. Apakah fungsi `payToUser` memanggil *helper function* `getPaymentLink` untuk akses API Flip?
-2. Apakah fungsi `payToUser` memanggil fungsi `save` pada `PaymentRepository` untuk menyimpan objek `Payment` ke dalam database?
+
+1. Apakah fungsi `payToUser` memanggil **setidaknya satu kali** *helper function* `getPaymentLink` untuk akses API Flip? (sintaks verifikasi pemanggilan *mock* ada di line 8)
+2. Apakah fungsi `payToUser` memanggil **setidaknya satu kali** fungsi `save` pada `PaymentRepository` untuk menyimpan objek `Payment` ke dalam database? (sintaks verifikasi pemanggilan *mock* ada di line 9)
 3. Apakah fungsi `payToUser` mengembalikan objek `Payment`, dengan isi yang sama seperti yang dikembalikan oleh API Flip?
 
-### `paymentCallback` sukses menyimpan status `WAITING_DISBURSEMENT` ketika status Payment Link `"SUCCESSFUL"` dan status Disbursement `"PENDING"`
+### Contoh 2: Fungsi `paymentCallback` sukses menyimpan status `WAITING_DISBURSEMENT` ketika status Payment Link `"SUCCESSFUL"` dan status Disbursement `"PENDING"`
 ```java
     @Test
     void testPaymentCallbackWithSuccessfulStatusAndPendingDisbursement() {
@@ -280,16 +306,20 @@ Selain itu, juga terdapat *stubbing* untuk fungsi `service.getPaymentLink(Paymen
 
 Fungsi `paymentCallback` bertujuan untuk meneruskan pembayaran lewat mekanisme *Disbursement* jika status Payment Link yang diberikan `"SUCCESSFUL"`.
 
-Terlihat bahwa terdapat *stubbing* untuk fungsi `paymentRepository.findByPaymentLinkId(Integer)` untuk menyimulasikan bahwa di database terdapat objek `payment`.
-Selain itu, juga terdapat *stubbing* untuk fungsi `service.disburseMoney(DisbursementRequest)` untuk mengembalikan objek `paymentLinkResponse`.
-Selain itu, kita juga perlu *set status* pada objek `paymentCallbackRequest` menjadi `"SUCCESSFUL"`.
-Selain itu, kita juga perlu *set status* pada objek `disbursementResponse` menjadi `"PENDING"` untuk menyimulasikan API Flip sedang melakukan proses *disbursement*.
+Berikut adalah penjelasan terkait *test case* ini:
+
+1. Di line 3, terdapat *stubbing* untuk fungsi `paymentRepository.findByPaymentLinkId(Integer)` untuk menyimulasikan bahwa di database terdapat objek `payment`.
+2. Di line 4, dilakukan *set status* pada objek `paymentCallbackRequest` menjadi `"SUCCESSFUL"`, untuk menyimulasikan API Flip memanggil *payment callback* dengan status "sukses" sehingga proses *disbursement* bisa dilakukan.
+3. Di line 5, terdapat *stubbing* untuk fungsi `service.disburseMoney(DisbursementRequest)` untuk mengembalikan objek `paymentLinkResponse`.
+4. Di line 6, dilakukan *set status* pada objek `disbursementResponse` menjadi `"PENDING"` untuk menyimulasikan API Flip sedang melakukan proses *disbursement*.
+
 *Test case* ini akan mengecek:
-1. Apakah fungsi `paymentCallback` memanggil *helper function* `disburseMoney` untuk akses API Flip?
-2. Apakah fungsi `paymentCallback` memanggil fungsi `save` pada `PaymentRepository` untuk menyimpan perubahan objek `Payment` ke dalam database?
+
+1. Apakah fungsi `paymentCallback` memanggil **setidaknya satu kali** *helper function* `disburseMoney` untuk akses API Flip? (sintaks verifikasi pemanggilan *mock* ada di line 10)
+2. Apakah fungsi `paymentCallback` memanggil **setidaknya satu kali** fungsi `save` pada `PaymentRepository` untuk menyimpan perubahan objek `Payment` ke dalam database?  (sintaks verifikasi pemanggilan *mock* ada di line 11)
 3. Apakah fungsi `paymentCallback` mengembalikan objek `Payment` dengan `status` berupa `"WAITING_DISBURSEMENT"`?
 
-### `paymentCallback` sukses menyimpan status `WAITING_DISBURSEMENT` ketika status Payment Link `"SUCCESSFUL"` dan status Disbursement `"DONE"`
+### Contoh 3: Fungsi `paymentCallback` sukses menyimpan status `WAITING_DISBURSEMENT` ketika status Payment Link `"SUCCESSFUL"` dan status Disbursement `"DONE"`
 ```java
     @Test
     void testPaymentCallbackWithSuccessfulStatusAndSuccessfulDisbursement() {
@@ -307,52 +337,63 @@ Selain itu, kita juga perlu *set status* pada objek `disbursementResponse` menja
     }
 ```
 
-Terlihat bahwa terdapat *stubbing* untuk fungsi `paymentRepository.findByPaymentLinkId(Integer)` untuk menyimulasikan bahwa di database terdapat objek `payment`.
-Selain itu, juga terdapat *stubbing* untuk fungsi `service.disburseMoney(DisbursementRequest)` untuk mengembalikan objek `paymentLinkResponse`.
-Selain itu, kita juga perlu *set status* pada objek `paymentCallbackRequest` menjadi `"SUCCESSFUL"`.
-Selain itu, kita juga perlu *set status* pada objek `disbursementResponse` menjadi `"DONE"` untuk menyimulasikan API Flip langsung selesai melakukan *disbursement*.
+Berikut adalah penjelasan terkait *test case* ini:
+
+1. Di line 3, terdapat *stubbing* untuk fungsi `paymentRepository.findByPaymentLinkId(Integer)` untuk menyimulasikan bahwa di database terdapat objek `payment`.
+2. Di line 4, dilakukan *set status* pada objek `paymentCallbackRequest` menjadi `"SUCCESSFUL"`, untuk menyimulasikan API Flip memanggil *payment callback* dengan status "sukses" sehingga proses *disbursement* bisa dilakukan.
+3. Di line 5, terdapat *stubbing* untuk fungsi `service.disburseMoney(DisbursementRequest)` untuk mengembalikan objek `paymentLinkResponse`.
+4. Di line 6, dilakukan *set status* pada objek `disbursementResponse` menjadi `"DONE"`, untuk menyimulasikan API Flip langsung selesai melakukan *disbursement*.
+
 *Test case* ini akan mengecek:
-1. Apakah fungsi `paymentCallback` memanggil *helper function* `disburseMoney` untuk akses API Flip?
-2. Apakah fungsi `paymentCallback` memanggil fungsi `save` pada `PaymentRepository` untuk menyimpan perubahan objek `Payment` ke dalam database?
+
+1. Apakah fungsi `paymentCallback` memanggil **setidaknya satu kali** *helper function* `disburseMoney` untuk akses API Flip? (sintaks verifikasi pemanggilan *mock* ada di line 10)
+2. Apakah fungsi `paymentCallback` memanggil **setidaknya satu kali** fungsi `save` pada `PaymentRepository` untuk menyimpan perubahan objek `Payment` ke dalam database? (sintaks verifikasi pemanggilan *mock* ada di line 11)
 3. Apakah fungsi `paymentCallback` mengembalikan objek `Payment` dengan `status` berupa `"SUCCESS"`?
 
 ### Tugas Anda
-- [ ] Silakan *copy* semua snippet kode yang telah dijelaskan ke dalam project Anda ke tempat yang sesuai.
-  - `testPayToUserSuccess` diletakkan di `PaymentServiceImplTest`.
-  - `testPaymentCallbackWithSuccessfulStatusAndPendingDisbursement` diletakkan di `CallbackServiceImplTest`.
-  - `testPaymentCallbackWithSuccessfulStatusAndSuccessfulDisbursement` diletakkan di `CallbackServiceImplTest`.
-
-### Latihan Mandiri: Buat *positive case*
+- [ ] Buat *test case* `testPayToUserSuccess` sesuai dengan arahan yang sudah diberikan.
+    - [ ] *Test case* diletakkan di dalam *test suite* `com.example.sibayar.service.payment.PaymentServiceImplTest`.
+    - [ ] Pastikan *test case* mengecek tiga hal yang disebutkan di arahan.
+- [ ] Buat *test case* `testPaymentCallbackWithSuccessfulStatusAndPendingDisbursement` sesuai dengan arahan yang sudah diberikan.
+    - [ ] *Test case* diletakkan di `com.example.sibayar.service.payment.CallbackServiceImplTest`.
+    - [ ] Pastikan *test case* mengecek tiga hal yang disebutkan di arahan.
+- [ ] Buat *test case* `testPaymentCallbackWithSuccessfulStatusAndSuccessfulDisbursement` sesuai dengan arahan yang sudah diberikan.
+    - [ ] *Test case* diletakkan di `com.example.sibayar.service.payment.CallbackServiceImplTest`.
+    - [ ] Pastikan *test case* mengecek tiga hal yang disebutkan di arahan.
+
+### Latihan Mandiri: Buat sebuah *positive case*
 - [ ] Buat *test case* `testPayToOtherSuccess` pada *test suite* `PaymentServiceImplTest` untuk mengecek:
-  1. Apakah fungsi `payToOtherDestination` memanggil *helper function* `getPaymentLink` untuk akses API Flip?
-  2. Apakah fungsi `payToOtherDestination` memanggil fungsi `save` pada `PaymentRepository` untuk menyimpan objek `Payment` ke dalam database?
-  3. Apakah fungsi `payToOtherDestination` mengembalikan objek `Payment`, dengan isi yang sama seperti yang dikembalikan oleh API Flip?
+    - [ ] Apakah fungsi `payToOtherDestination` memanggil *helper function* `getPaymentLink` untuk akses API Flip?
+    - [ ] Apakah fungsi `payToOtherDestination` memanggil fungsi `save` pada `PaymentRepository` untuk menyimpan objek `Payment` ke dalam database?
+    - [ ] Apakah fungsi `payToOtherDestination` mengembalikan objek `Payment`, dengan isi yang sama seperti yang dikembalikan oleh API Flip?
 
-### Latihan Mandiri: Buat *negative case*
+### Latihan Mandiri: Buat beberapa *negative case*
 - [ ] Buat *test case* `testPaymentCallbackWithSuccessfulStatusButCancelledDisbursement` pada *test suite* `CallbackServiceImplTest` untuk mengecek:
-  1. Apakah fungsi `paymentCallback` memanggil *helper function* `getPaymentLink` untuk akses API Flip?
-  2. Apakah fungsi `paymentCallback` memanggil fungsi `save` pada `PaymentRepository` untuk menyimpan perubahan objek `Payment` ke dalam database?
-  3. Apakah fungsi `paymentCallback` mengembalikan objek `Payment` dengan `status` berupa `"DISBURSEMENT_FAILED"`?
-  - **CATATAN**: `status` pada `disbursementResponse` harus diganti dengan `"CANCELLED"`.
+    - [ ] Apakah fungsi `paymentCallback` memanggil **setidaknya satu kali** *helper function* `getPaymentLink` untuk akses API Flip?
+    - [ ] Apakah fungsi `paymentCallback` memanggil **setidaknya satu kali** fungsi `save` pada `PaymentRepository` untuk menyimpan perubahan objek `Payment` ke dalam database?
+    - [ ] Apakah fungsi `paymentCallback` mengembalikan objek `Payment` dengan `status` berupa `"DISBURSEMENT_FAILED"`?
+    - **CATATAN**: `status` pada `disbursementResponse` harus diganti dengan `"CANCELLED"`.
 - [ ] Buat *test case* `testPaymentCallbackWithCancelledStatus` pada *test suite* `CallbackServiceImplTest` untuk mengecek:
-  1. Apakah fungsi `paymentCallback` **TIDAK** memanggil *helper function* `getPaymentLink` untuk akses API Flip?<br />
+    - [ ] Apakah fungsi `paymentCallback` **TIDAK** memanggil *helper function* `getPaymentLink` untuk akses API Flip?<br />
       **HINT**: gunakan
       ```java
       verify(service, atMost(0)).disburseMoney(any(DisbursementRequest.class))
       ```
       untuk mengecek bahwa *helper function* tidak dipanggil.
-  2. Apakah fungsi `paymentCallback` memanggil fungsi `save` pada `PaymentRepository` untuk menyimpan perubahan objek `Payment` ke dalam database?
-  3. Apakah fungsi `paymentCallback` mengembalikan objek `Payment` dengan `status` berupa `"PAYMENT_FAILED"`?
-  - **CATATAN**: `status` pada `paymentCallbackRequest` harus diganti dengan `"CANCELLED"`.
+    - [ ] Apakah fungsi `paymentCallback` memanggil **setidaknya satu kali** fungsi `save` pada `PaymentRepository` untuk menyimpan perubahan objek `Payment` ke dalam database?
+    - [ ] Apakah fungsi `paymentCallback` mengembalikan objek `Payment` dengan `status` berupa `"PAYMENT_FAILED"`?
+    - **CATATAN**: `status` pada `paymentCallbackRequest` harus diganti dengan `"CANCELLED"`.
 
 
 ## Menguji Apakah Fungsi Mengeluarkan *Exception* dalam Suatu *Test Case*
 
 *Unit test* tidak hanya mencakup *positive case* (dalam kasus ini: mengembalikan objek `Payment`),
 akan tetapi juga perlu mencakup *negative case* (dalam kasus ini: mengeluarkan sebuah *exception*).
+
+Untuk mengecek apakah aplikasi mengeluarkan *exception*, kita bisa memanfaatkan fungsi `assertThrows`.
 Sebagai contoh, berikut adalah beberapa *negative case* yang bisa Anda gunakan:
 
-### `payToUser` pada `PaymentServiceImpl` akan mengembalikan *error* ketika user ID dari *sender* dan *destination* sama.
+### Contoh 1: `payToUser` pada `PaymentServiceImpl` akan mengembalikan *error* ketika user ID dari *sender* dan *destination* sama.
 ```java
     @Test
     void testPayToUserFailWhenSenderAndDestinationAreTheSame() {
@@ -364,7 +405,7 @@ Sebagai contoh, berikut adalah beberapa *negative case* yang bisa Anda gunakan:
 
 *Test case* ini akan mengecek apakah *exception* `SelfPaymentException` dikeluarkan jika user ID dari *sender* dan *destination* sama.
 
-### `payToUser` pada `PaymentServiceImpl` akan mengembalikan *error* jika Flip API sedang tidak bisa diakses.
+### Contoh 2: `payToUser` pada `PaymentServiceImpl` akan mengembalikan *error* jika Flip API sedang tidak bisa diakses.
 ```java
     @Test
     void testPayToUserThrowsExceptionWhenAPIIsUnreachable() {
@@ -378,13 +419,17 @@ Sebagai contoh, berikut adalah beberapa *negative case* yang bisa Anda gunakan:
     }
 ```
 
-Terlihat bahwa terdapat *stubbing* untuk fungsi `userRepository.findById(Integer)` untuk mengembalikan objek *mock* `user`.
-Selain itu, juga terdapat *stubbing* untuk fungsi `service.getPaymentLink(PaymentLinkRequest)` untuk melempar *exception* `APIUnreachableException`.
+Berikut adalah penjelasan mengenai *stubbing* pada *test case* ini:
+
+1. Di line 3, terdapat *stubbing* untuk fungsi `userRepository.findById(Integer)` untuk mengembalikan objek *mock* `user`.
+2. Di line 4, terdapat *stubbing* untuk fungsi `service.getPaymentLink(PaymentLinkRequest)` untuk melempar *exception* `APIUnreachableException`.
+
 *Test case* ini akan mengecek:
-1. Apakah fungsi `payToUser` meneruskan *exception* `APIUnreachableException`?
-2. Apakah fungsi `payToUser` memanggil *helper function* `getPaymentLink` untuk akses API Flip?
 
-### `paymentCallback` pada `CallbackServiceImpl` akan mengembalikan *error* jika pembayaran lewat payment link sukses, namun Flip API untuk *disbursement* sedang tidak bisa diakses.
+1. Apakah fungsi `payToUser` meneruskan *exception* `APIUnreachableException`? (pengecekan di line 6)
+2. Apakah fungsi `payToUser` memanggil *helper function* `getPaymentLink` untuk akses API Flip? (sintaks verifikasi pemanggilan *mock* ada di line 9)
+
+### Contoh 3: `paymentCallback` pada `CallbackServiceImpl` akan mengembalikan *error* jika pembayaran lewat payment link sukses, namun Flip API untuk *disbursement* sedang tidak bisa diakses.
 ```java
     @Test
     void testPaymentCallbackWithSuccessfulStatusThrowsExceptionWhenAPIIsUnreachable() {
@@ -399,25 +444,35 @@ Selain itu, juga terdapat *stubbing* untuk fungsi `service.getPaymentLink(Paymen
     }
 ```
 
-Terlihat bahwa terdapat *stubbing* untuk fungsi `paymentRepository.findByPaymentLinkId(Integer)` untuk mengembalikan objek `payment`.
-Selain itu, juga terdapat *stubbing* untuk fungsi `service.disburseMoney(DisbursementRequest)` untuk melempar *exception* `APIUnreachableException`.
-Selain itu, kita juga perlu *set status* pada objek `paymentCallbackRequest` menjadi `"SUCCESSFUL"`,
-karena akses API Flip untuk *disbursement* hanya akan diakses jika status *payment link* sudah `SUCCESSFUL`.
+Berikut adalah penjelasan mengenai *stubbing* pada *test case* ini:
+
+1. Di line 3, terdapat *stubbing* untuk fungsi `paymentRepository.findByPaymentLinkId(Integer)` untuk mengembalikan objek `payment`.
+2. Di line 4, dilakukan *set status* pada objek `paymentCallbackRequest` menjadi `"SUCCESSFUL"`,
+    karena akses API Flip untuk *disbursement* hanya akan diakses jika status *payment link* sudah `SUCCESSFUL`.
+3. Di line 5, Selain itu, juga terdapat *stubbing* untuk fungsi `service.disburseMoney(DisbursementRequest)` untuk melempar *exception* `APIUnreachableException`.
+    Ini untuk menyimulasikan ketika API Flip sedang tidak bisa diakses.
+
 *Test case* ini akan mengecek:
-1. Apakah fungsi `payToUser` meneruskan *exception* `APIUnreachableException`?
-2. Apakah fungsi `payToUser` memanggil *helper function* `disburseMoney` untuk akses API Flip?
+
+1. Apakah fungsi `payToUser` meneruskan *exception* `APIUnreachableException`? (pengecekan di line 8)
+2. Apakah fungsi `payToUser` memanggil *helper function* `disburseMoney` untuk akses API Flip? (sintaks verifikasi pemanggilan *mock* ada di line 11)
 
 ### Tugas Anda
-- [ ] Silakan *copy* semua snippet kode yang telah dijelaskan ke dalam project Anda ke tempat yang sesuai.
-  - `testPayToUserFailWhenSenderAndDestinationAreTheSame` diletakkan di `PaymentServiceImplTest`.
-  - `testPayToUserThrowsExceptionWhenAPIIsUnreachable` diletakkan di `PaymentServiceImplTest`.
-  - `testPaymentCallbackWithSuccessfulStatusThrowsExceptionWhenAPIIsUnreachable` diletakkan di `CallbackServiceImplTest`.
+- [ ] Buat *test case* `testPayToUserFailWhenSenderAndDestinationAreTheSame` sesuai dengan arahan yang sudah diberikan.
+    - [ ] *Test case* diletakkan di dalam *test suite* `com.example.sibayar.service.payment.PaymentServiceImplTest`.
+    - [ ] Pastikan *test case* mengecek tiga hal yang disebutkan di arahan.
+- [ ] Buat *test case* `testPayToUserThrowsExceptionWhenAPIIsUnreachable` sesuai dengan arahan yang sudah diberikan.
+    - [ ] *Test case* diletakkan di `com.example.sibayar.service.payment.PaymentServiceImplTest`.
+    - [ ] Pastikan *test case* mengecek tiga hal yang disebutkan di arahan.
+- [ ] Buat *test case* `testPaymentCallbackWithSuccessfulStatusThrowsExceptionWhenAPIIsUnreachable` sesuai dengan arahan yang sudah diberikan.
+    - [ ] *Test case* diletakkan di `com.example.sibayar.service.payment.CallbackServiceImplTest`.
+    - [ ] Pastikan *test case* mengecek tiga hal yang disebutkan di arahan.
 
 
 ### Latihan Mandiri: Buat *negative case*
 - [ ] Buat *test case* `testPayToOtherThrowsExceptionWhenAPIIsUnreachable` pada *test suite* `PaymentServiceImplTest` untuk mengecek:
-  1. Apakah fungsi `payToOtherDestination` meneruskan *exception* `APIUnreachableException`?
-  2. Apakah fungsi `payToOtherDestination` menjalankan *helper function* `getPaymentLink` untuk akses API Flip?
+    - [ ] Apakah fungsi `payToOtherDestination` meneruskan *exception* `APIUnreachableException`?
+    - [ ] Apakah fungsi `payToOtherDestination` memanggil **setidaknya satu kali** *helper function* `getPaymentLink` untuk akses API Flip?
 
 
 ## *Refactoring*: Bagaimana jika SIBAYAR bisa menggunakan lebih dari satu Payment Gateway?
@@ -427,76 +482,98 @@ Bagaimana jika suatu hari kita tidak menggunakan Flip sebagai *payment gateway*?
 Salah satu cara yang dapat kita lakukan adalah memisahkan *helper function* `getPaymentLink` dan `disburseMoney` menjadi sebuah *class* tersendiri di bawah package `com.example.sibayar.external.paymentgateway`.
 Lalu, bagaimana cara kita menyesuaikan implementasi dan *unit test* kita ketika ada perubahan desain tersebut?
 
+Pada bagian ini, kita akan melakukan proses *refactoring* beserta penyesuaian *unit test* yang perlu dilakukan.
+
 ### Tugas Anda
-- [ ] Buat interface baru `PaymentGatewayAPI`, dengan menggunakan *snippet* berikut:
-  ```java
-  public interface PaymentGatewayAPI {
-      PaymentLinkResponse getPaymentLink(PaymentLinkRequest request);
-      DisbursementResponse disburseMoney(DisbursementRequest request);
-  }
-  ```
-- [ ] Buat class baru `FlipAPI`, dengan menggunakan *snippet* berikut:
-  ```java
-  @Service("flipAPI")
-  @RequiredArgsConstructor
-  public class FlipAPI implements PaymentGatewayAPI {
-      @Value("${sibayar.flip.baseUrl}")
-      private String baseUrl;
-      @Value("${sibayar.flip.apiKey}")
-      private String apiKey;
-      private HttpClient client = HttpClient.newHttpClient();
-
-      public PaymentLinkResponse getPaymentLink(PaymentLinkRequest request) {
-          // TODO: Pindahkan isi fungsi getPaymentLink di PaymentServiceImpl ke sini.
-      }
-
-      public DisbursementResponse disburseMoney(DisbursementRequest request) {
-          // TODO: Pindahkan isi fungsi disburseMoney di CallbackServiceImpl ke sini.
-      }
-
-      private String getBasicAuthHeader(String username, String password) {
-          String valueToEncode = username + ":" + password;
-          return "Basic " + Base64.getEncoder()
-                                  .encodeToString(valueToEncode.getBytes());
-      }
-  }
-  ```
-- [ ] Pada `PaymentServiceImpl` dan `CallbackServiceImpl`, buat koneksi baru ke `PaymentGatewayAPI` dengan menggunakan *snippet* berikut:
-  ```java
-      @Qualifier("flipAPI")
-      private final PaymentGatewayAPI api;
-  ```
-- [ ] Gunakan `api` untuk mengakses fungsi `getPaymentLink` dan `disburseMoney` yang telah dipindahkan.
+- [ ] Buat *interface* baru `PaymentGatewayAPI` di package `com.example.sibayar.external.paymentgateway`, dengan menggunakan *snippet* berikut:
+    ```java
+    public interface PaymentGatewayAPI {
+        PaymentLinkResponse getPaymentLink(PaymentLinkRequest request);
+        DisbursementResponse disburseMoney(DisbursementRequest request);
+    }
+    ```
+    Tujuan dari *interface* `PaymentGatewayAPI` adalah untuk memastikan bahwa semua *class* penghubung dengan API *payment gateway* dapat diakses dengan cara yang sama.
+- [ ] Buat *class* baru `FlipAPI` di packakge `com.example.sibayar.external.paymentgateway`, dengan menggunakan *snippet* berikut:
+    ```java
+    @Service("flipAPI")
+    @RequiredArgsConstructor
+    public class FlipAPI implements PaymentGatewayAPI {
+        @Value("${sibayar.flip.baseUrl}")
+        private String baseUrl;
+        @Value("${sibayar.flip.apiKey}")
+        private String apiKey;
+        private HttpClient client = HttpClient.newHttpClient();
+
+        public PaymentLinkResponse getPaymentLink(PaymentLinkRequest request) {
+            // TODO: Pindahkan isi fungsi getPaymentLink di PaymentServiceImpl ke sini.
+        }
+
+        public DisbursementResponse disburseMoney(DisbursementRequest request) {
+            // TODO: Pindahkan isi fungsi disburseMoney di CallbackServiceImpl ke sini.
+        }
+
+        private String getBasicAuthHeader(String username, String password) {
+            String valueToEncode = username + ":" + password;
+            return "Basic " + Base64.getEncoder()
+          .encodeToString(valueToEncode.getBytes());
+        }
+    }
+    ```
+    Lakukan juga beberapa hal berikut:
+
+    - [ ] Pindahkan juga isi *method* `getPaymentLink` yang sebelumnya ada di `com.example.sibayar.service.payment.PaymentServiceImpl`, ke dalam *method* `getPaymentLink` yang ada di `FlipAPI`.
+    - [ ] Pindahkan juga isi *method* `disburseMoney` yang sebelumnya ada di `com.example.sibayar.service.payment.CallbackServiceImpl`, ke dalam *method* `getPaymentLink` yang ada di `FlipAPI`.
+
+- [ ] Pada `PaymentServiceImpl` dan `CallbackServiceImpl`, buat koneksi baru ke implementasi dari `PaymentGatewayAPI` dengan cara membuat *instance variable* baru. Gunakan *snippet* berikut untuk diletakkan di definisi *class* dari `PaymentServiceImpl` dan `CallbackServiceImpl`.
+    ```java
+        @Qualifier("flipAPI")
+        private final PaymentGatewayAPI api;
+    ```
+    `@Qualifier("flipAPI")` akan otomatis melakukan *dependency injection* sehingga variabel `api` akan berisi objek dari `FlipAPI`.
+- [ ] Gunakan `api` untuk mengakses fungsi `getPaymentLink` dan `disburseMoney` yang telah dipindahkan ke `FlipAPI`. Misal dari sebelumnya:
+    ```java
+            PaymentLinkResponse apiResponse = getPaymentLink(apiRequest);
+    ```
+    menjadi seprti berikut:
+    ```java
+            PaymentLinkResponse apiResponse = api.getPaymentLink(apiRequest);
+    ```
 - [ ] Tambahkan objek *mock* untuk `PaymentGatewayAPI` pada *test suite* `PaymentServiceImplTest` dan `CallbackServiceImplTest` dengan menggunakan *snippet* berikut:
-  ```java
-      @Mock
-      private PaymentGatewayAPI flipAPI;
-  ```
-- [ ] Gunakan objek *mock* `flipAPI` untuk menggantikan pemanggilan fungsi `getPaymentLink` dan `disburseMoney` pada setiap `test case`. Misal:
-  ```java
-      when(service.disburseMoney(any(DisbursementRequest.class))).thenReturn(disbursementResponse);
-      // ...
-      verify(service, atLeastOnce()).disburseMoney(any(DisbursementRequest.class));
-  ```
-  menjadi seperti berikut:
-  ```java
-      when(flipAPI.disburseMoney(any(DisbursementRequest.class))).thenReturn(disbursementResponse);
-      // ...
-      verify(flipAPI, atLeastOnce()).disburseMoney(any(DisbursementRequest.class));
-  ```
-
-## Latihan Mandiri Tambahan:
-- [ ] Lengkapi semua *test case* hingga Line Coverage menyentuh 100%.
-- [ ] Buat kode *test case* yang *meaningful* dan *thorough*.
+    ```java
+        @Mock
+        private PaymentGatewayAPI flipAPI;
+    ```
+- [ ] Gunakan objek *mock* `flipAPI` untuk menggantikan pemanggilan fungsi `getPaymentLink` dan `disburseMoney` pada setiap *test case*. Misal dari sebelumnya:
+    ```java
+        when(service.disburseMoney(any(DisbursementRequest.class))).thenReturn(disbursementResponse);
+        // ...
+        verify(service, atLeastOnce()).disburseMoney(any(DisbursementRequest.class));
+    ```
+    menjadi seperti berikut:
+    ```java
+        when(flipAPI.disburseMoney(any(DisbursementRequest.class))).thenReturn(disbursementResponse);
+        // ...
+        verify(flipAPI, atLeastOnce()).disburseMoney(any(DisbursementRequest.class));
+    ```
+
+## Latihan Mandiri Tambahan
+- [ ] Lengkapi semua *test case* hingga *Line Coverage* menyentuh 100%.
+- [ ] Buat kode *test case* yang *meaningful* dan *thorough*. Cek apakah dependensi eksternal seperti *repository* atau *payment gateway* API dipanggil sesuai kebutuhan setiap *test case*.
+- [ ] Integrasikan *project* Anda dengan SonarQube.<br />
+    Contoh *project* SIBAYAR yang sudah memenuhi *Line Coverage* 100%:
+    ![Screenshot SonarQube SIBAYAR](./images/day_2_tdd_-_sonarqube_sibayar.png)
 
 ## Penutup
 Kita sudah bersama-sama membuat *unit test* untuk Service, lengkap dengan cara  menggunakan *mock* dan *stub*.
 
 Untuk bahan diskusi saat refleksi:
-- [ ] Apakah Line Coverage 100% menjamin tidak ada bug?
-- [ ] Bagaimana jika kita langsung melakukan modifikasi *database* atau mengakses langsung *library* atau API eksternal saat kita melakukan *unit test*? Apa dampaknya bagi konsistensi hasil dari *unit test*?
+
+- [ ] Apakah *Line Coverage* 100% menjamin tidak ada *bug*? Apakah *Line Coverage* 100% menjamin aspek **FIRST *principle*** terutama aspek ***Thorough***?
+- [ ] Bagaimana jika kita langsung melakukan modifikasi *database* atau mengakses langsung *library* atau API eksternal saat kita melakukan *unit test*? Apa dampaknya bagi konsistensi hasil dari *unit test*? Apa dampaknya bagi **FIRST *principle*** pada *unit test* yang dibuat, terutama aspek ***Fast***, ***Isolated***, dan ***Repeatable***?
 - [ ] Apa kesulitan yang dialami Bapak/Ibu ketika menjalani tutorial ini?
 
+Untuk hari ketiga, kita akan mendalami mengenai Functional Test dan Behaviour-Driven Development (BDD).
 
 
 [1]: https://docs.google.com/presentation/d/1f1vpyYOu3GSyIeyqGLU-D6REBn0ACN81?rtpof=true&usp=drive_fs
+[2]: https://docs.flip.id/
diff --git a/docs/workshops/images/day_2_tdd_-_sonarqube_sibayar.png b/docs/workshops/images/day_2_tdd_-_sonarqube_sibayar.png
new file mode 100644
index 0000000000000000000000000000000000000000..25a4475c93314ce884dfcdcc51c87492b9ffd3f9
Binary files /dev/null and b/docs/workshops/images/day_2_tdd_-_sonarqube_sibayar.png differ