Konsep Mocking Pada Javascript: Sebuah Pendahuluan

Mock memungkinkan kita untuk membuat unittest yang benar-benar menguji suatu unit di software (bisa class atau function) tanpa mempedulikan dependensi.

ilustrasi mock pada test (https://piraveenaparalogarajah.medium.com/what-is-mocking-in-testing-d4b0f2dbe20a)

Pendahuluan

Katakanlah Anda merupakan seorang front-end developer yang ingin membuat sebuah website yang membutuhkan API eksternal untuk memperoleh data sehingga Anda tidak tahu bagaimana implementasinya dari API tersebut. Misalnya, Anda ingin menerapkan TDD dalam proses pengembangan website tersebut sehingga tentunya langkah awal yang perlu dilakukan adalah membuat unit-test. Anda ingin menguji unit kode yang menampilkan data dari API yang dimaksud apabila berhasil serta menampilkan halaman error apabila data yang diperoleh dari API mengalami kegagalan. Bagaimana mengatasi permasalahan dependensi antara unit yang dimaksud dengan eksternal API? Tentunya tidak mungkin perlu dibuat implementasi dari API yang dimaksud. Bagaimana dengan memanggil API tersebut secara langsung pada test? Tentunya bisa saja namun terdapat satu permasalahan. Apa yang terjadi apabila terjadi error pada bagian API-nya (down, maintenance, dsb)? Unittest yang kita buat akan gagal walaupun secara implementasi sendiri tidak ada yang salah. Maka langkah bijak yang bisa dilakukan adalah melakukan decoupling antara API yang dipanggil dengan fungsi yang memanggil API tersebut pada unit-testing. Lalu bagaimana cara mensimulasikan proses mengeluarkan output tersebut walaupun Anda hanya mengetahui keluaran data dari API tersebut?

Contoh kasus lainnya, Anda frontend developer di sebuah perusahaan dan Anda bekerja sama dengan backend developer mengerjakan satu proyek dengan rentang waktu yang cukup singkat. Katakanlah backend developer ini bernama Anto. Anda ingin membuat test yang menguji fungsi pemanggilan endpoint yang dibuat oleh Anto. Namun masalahnya adalah, Anto belum menyelesaikan implementasi endpoint dan apabila Anda menunggu, tentunya akan menimbulkan blocker dan tidak mungkin Anda harus menunggu Anto untuk bisa mulai mengimplementasikan aplikasi frontend mengingat waktu yang singkat. Bagaimana Anda bisa membuat test yang menguji fungsi tersebut tanpa mempedulikan adanya endpoint tersebut atau tidak? Di sinilah suatu mock diperlukan.

Apa itu Mock?

Menurut merriam-webster, mock mempunyai definisi sebagai berikut.

to imitate (someone or something) closely : mimic

Jadi mock pada dasarnya kegiatan meniru sesuatu. Dalam konteks unit-testing, mock adalah meniru atau mensimulasikan behaviour dari suatu dependensi pada suatu unit kode yang ingin dites sehingga fungsi atau kelas yang ingin kita tes sudah terisolasi dengan dependensi-dependensinya. Dengan mengisolasi unit yang ingin kita tes dan dependensi-dependensinya, maka scope pengujian untuk tes kita hanya terbatas pada suatu fungsi/kelas yang dimaksud. Hal tersebut merupakan esensi dari unit-test sendiri yakni menguji satu unit, bukan beberapa unit. Secara sederhananya, mock merupakan fungsi atau objek imitasi yang mensimulasikan behaviour keluaran dari fungsi atau objek aslinya. Secara ilustrasi mungkin sebagai berikut.

Anggap misalkan ada fungsi A yang memanggil fungsi B. Fungsi B anggaplah suatu fungsi black box sehingga kita tidak tahu bagaimana implementasinya namun kita tahu keluaran dari fungsi B. Fungsi A membutuhkan fungsi B pada implementasinya. Maka solusinya adalah kita membuat fungsi imitasi dari fungsi B yangmana fungsi tersebut mengeluarkan berbagai kemungkinan keluaran dari fungsi B. Fungsi tersebut digunakan pada unit test fungsi A sehingga kita bisa menguji fungsi A secara independen tanpa tergantung terhadap detil implementasi fungsi B.

Implementasi Pada Javascript

Pada website frontend yang kami kerjakan, terdapat beberapa komponen yang diperlukan. Salah satu komponen yang dimaksud adalah komponen yang berfungsi untuk menghubungkan antara endpoint di backend dengan frontend. Untuk artikel ini saya mengambil contoh fungsi untuk memanggil endpoint login. Implementasi testing menggunakan library jest untuk unit-testing pada javascript

Pada kode tersebut, Saya menguji dua kemungkinan kasus pada proses login yakni ketika proses login berhasil dan ketika proses login gagal.

Pada baris jest(“axios”) , jest akan mensubsitusikan semua pemanggilan instance axios dengan mock instance. Sebagai catatan axios merupakan salah satu library yang digunakan untuk melakukan pemanggilan HTTP request ke suatu endpoint.

Pada pengujian untuk kasus login berhasil, perhatikan terdapat perintah “axios.post.mockResolvedValueOnce(mockResult)”. Yang dilakukan perintah tersebut adalah setiap kali terjadi pemanggilan method axios.post, maka keluarkan “mockResult”. Hal ini mensimulasikan proses pemanggilan API yang berhasil dengan mengeluarkan keluaran mirip seperti pada “mockResult”. Hal ini untuk melakukan tes apakah fungsi login mengeluarkan respon yang diharapkan (“accessToken” yang sama, “refreshToken” yang sama, dsb) apabila proses pemanggilan ke endpoint mengeluarkan respons sukses(respons 200).

Lalu pada pengujian untuk kasus login gagal, perhatikan terdapat “axios.post.mockRejectedValueOnce(mockResult)”. Endpoint untuk login akan mengeluarkan error response (respons dengan kode yang memiliki digit terkiri 4) beserta data yang menampilkan deskripsi error-nya sehingga kita bisa simulasikan dengan perintah tersebut. Perintah tersebut pada dasarnya adalah untuk setiap pemanggilan method axios.post, maka keluarkan error response beserta data yang menampilkan deskripsi error. Hal ini untuk melakukan tes apakah fungsi login men-throw error yang diperoleh dari error response pada pemanggilan endpoint yang gagal.

Kapan Kita Perlu Membuat Mock?

Menurut Saya kita perlu membuat mock untuk melakukan unit test serta kita bisa mengetahui apa saja respons yang akan dikeluarkan suatu dependensi untuk berbagai kasus. Selain itu, fungsi atau kelas yang ingin kita unit-test mempunyai dependensi serta dependensi yang dibutuhkan mempunyai sifat yang inderterministik (sebagai contoh endpoint API eksternal). Kita bisa menggunakan mock untuk melakukan separation of concerns pada unit-testing antara satu unit dengan unit lainnya.

Bagaimana Mock Bisa Mengefisiensi Pengerjaan Proyek Perangkat Lunak

Selama PPL ini kita perlu membuat unit-test. Ketika sprint 1 berjalan, Saya mendapat tugas untuk mengerjakan komponen pada frontend yang mengintegrasikan aplikasi frontend dengan endpoint login pada backend. Karena proses sprint yang menurut saya cukup singkat (2 minggu), saya merasa tidak perlu berleha-leha untuk bisa mengerjakan komponen ini. Apalagi komponen ini cukup krusial digunakan oleh frontend. Oleh karena itu, langkah awal yang saya lakukan adalah membuat mock atau fake endpoint yang saya rancang sendiri. Dengan langkah ini saya berhasil mengimplementasikan komponen ini bahkan lebih awal sebelum endpoint login berhasil diselesaikan oleh teman saya.

waktu pengerjaan untuk membuat komponen integrasi frontend dan endpoint
waktu ketika endpoint login selesai diimplementasikan

Maka setelah endpoint login sebenarnya sudah selesai, saya hanya perlu melakukan sedikit modifikasi untuk menyesuaikan dengan endpoint sebenarnya.

waktu merevisi komponen

Maka pelajaran yang saya peroleh dari menggunakan mock ini adalah, mock bisa mengefisiensi proses pengembangan karena tidak harus menunggu dependensi sebenarnya berhasil diimplementasikan. Kita cukup membuat dependensi palsu atau mock dengan asumsi kita sendiri lalu menyesuaikannya dengan dependensi aslinya apabila dependensi tersebut sudah selesai diimplementasikan.

Kesimpulan

Dengan membuat mock, kita bisa mempercepat proses development karena kita tidak perlu menunggu apakah dependensi sudah diimplementasikan atau tidak. Selain itu, kita juga bisa membuat test yang benar-benar merupakan unit-test karena menguji fungsi atau kelas yang ingin kita uji sudah terisolasi dengan dependensi pada proses unit testing. Sekian dari Saya dan mudah-mudahan dapat bermanfaat.