Materi
Unit test memeriksa satu bagian program, sedapat mungkin terpisah dari bagian lain, supaya kegagalannya menunjuk bagian itu. Masalahnya, banyak fungsi bergantung pada sesuatu yang lambat, acak, atau berdampak keluar: mengirim SMS, membaca jam, mengambil angka acak. Pengganti ketergantungan selama test disebut test double. Martin Fowler mencatat istilah dari Gerard Meszaros: dummy hanya mengisi parameter dan tidak dipakai; fake berupa implementasi sungguhan yang disederhanakan; stub memberi jawaban yang sudah disiapkan; spy adalah stub yang juga mencatat cara ia dipanggil; mock diprogram dengan harapan tentang panggilan yang akan diterimanya.
unittest.mock menyediakan objek Mock yang bisa memainkan peran-peran itu. Mock menerima panggilan apa pun, mencatatnya, dan mengembalikan return_value. Sesudah fungsi yang diuji berjalan, catatan itu diperiksa: assert_called_once_with(...) untuk tepat satu panggilan dengan argumen tertentu, assert_not_called() untuk memastikan tidak ada panggilan, call_count untuk jumlahnya. Cara paling sederhana memasangnya adalah lewat parameter: fungsi menerima pengirimnya sebagai argumen, dan test memberinya Mock.
from unittest.mock import Mock
def umumkan_libur(daftar_hp, tanggal, kirim):
for hp in daftar_hp:
kirim(hp, f"Kantor libur {tanggal}")
kirim = Mock()
umumkan_libur(["0811", "0812"], "17 Agustus", kirim)
print(kirim.call_count) # 2
kirim.assert_called_with("0812", "Kantor libur 17 Agustus")
Bila ketergantungannya dipanggil langsung dari dalam fungsi, misalnya random.randint, patch menggantinya sementara. Di dalam blok with patch("random.randint", return_value=4):, setiap panggilan random.randint mengembalikan 4; sesudah blok selesai, fungsi aslinya kembali. Dokumentasi unittest.mock menegaskan aturan letaknya: ganti nama di tempat nama itu dicari saat dipakai, bukan di tempat ia didefinisikan.
import random
from unittest.mock import patch
def lempar_dadu():
return random.randint(1, 6)
with patch("random.randint", return_value=4) as palsu:
print(lempar_dadu()) # 4
palsu.assert_called_once_with(1, 6)