Mengolok - jangan menggigit!
Mereka dirancang untuk membantu Anda membuat pengujian yang lebih sederhana dan lebih andal. Dalam rangkaian artikel ini, saya akan menunjukkan kepada Anda pola yang saya andalkan saat mengejek (atau "mematikan") komponen React.
Berikut adalah contoh yang bagus dari rintisan komponen. Saya menggunakan
jest.mock
, yang akan kita lihat lebih detail di bawah.
jest.mock("../src/PostContent", () => ({
PostContent: jest.fn(() => (
<div data-testid="PostContent" />
))
}))
Stub komponen React biasanya tidak terlihat lebih rumit. Perhatikan nilai stub yang sangat sederhana (
div
) dan atribut data-testid
yang sangat memudahkan kita untuk menemukan instance yang dirender di DOM. Sesuai ketentuan, pengenal pengujian yang digunakan harus cocok dengan nama komponen. Dalam hal ini, memang demikian PostContent
.
Sebelum kita melihat bagaimana mereka digunakan, pertama-tama mari kita ingat apa itu tiruan dan mengapa Anda mungkin ingin menggunakannya.
Apa itu tiruan?
Di dunia JavaScript, istilah tiruan sangat banyak digunakan untuk merujuk pada implementasi tiruan atau pengujian ganda . Penerapan palsu hanyalah nilai yang menggantikan yang lain dalam kode produksi Anda saat pengujian Anda berjalan. Mereka mencoba antarmuka objek yang diganti, sehingga kode Anda lainnya berfungsi seolah-olah tidak ada penggantinya.
Ada beberapa alasan berbeda mengapa Anda mungkin ingin melakukan ini; kita akan melihatnya dengan contoh.
Jika Anda tertarik untuk mempelajari lebih lanjut tentang implementasi tiruan, baca buku Martin Fowler Mocks Are Not Stubs .
Bercanda dan mengejek
Jest memiliki fitur
jest.mock
yang memungkinkan Anda mengejek seluruh modul yang Anda ganti. Dalam tutorial ini, saya fokus pada fitur ini, meskipun ada cara lain untuk mengganti objek di JavaScript.
Dalam buku Mastering React Test-Driven Development, saya menggunakan impor modul bernama ES6 untuk membuat tes ganda. Pendekatan ini memberikan sedikit lebih banyak fleksibilitas, tetapi terlihat sedikit lebih hackish.
Jest jest.mock
Dikatakan mengolok-olok memastikan tes Anda cepat dan tidak rapuh .
Meskipun ini benar, ini bukanlah alasan utama saya menggunakan ejekan.
Saya menggunakan ejekan karena mereka membantu saya menjaga tes saya tetap independen satu sama lain.
Untuk memahami mengapa ini terjadi, mari kita lihat sebuah contoh.
Kenapa moki?
Di bawah ini adalah daftar komponen
BlogPage
yang melakukan dua hal: mengambil id
dari properti url
dan kemudian menampilkan PostContent
komponen dengannya id
.
const getPostIdFromUrl = url =>
url.substr(url.lastIndexOf("/") + 1)
export const BlogPage = ({ url }) => {
const id = getPostIdFromUrl(url)
return (
<PostContent id={id} />
)
}
Bayangkan Anda menulis pengujian untuk komponen ini, dan semua pengujian Anda disertakan
BlogPage.test.js
, yang merupakan satu rangkaian pengujian yang mencakup komponen BlogPage
dan PostContent
.
Pada titik ini, Anda tidak perlu mengolok-olok belum: kita belum melihat
PostContent
itu belum, tetapi mengingat ukuran BlogPage
, sebenarnya tidak ada kebutuhan untuk memiliki dua suite tes terpisah, karena BlogPage
itu umumnya sederhana PostContent
.
Sekarang bayangkan menambahkan fungsionalitas ke
BlogPage
y dan y PostContent
. Sebagai pengembang berbakat, Anda menambahkan lebih banyak fitur setiap hari.
Menjadi lebih sulit untuk mempertahankan tes agar berfungsi. Setiap pengujian baru memiliki penyiapan yang lebih kompleks, dan rangkaian pengujian mulai menghabiskan lebih banyak waktu Anda - beban yang sekarang perlu didukung.
Ini adalah masalah umum dan saya melihatnya sepanjang waktu di basis kode React. Rangkaian pengujian yang bahkan perubahan paling sederhana pun akan mengakibatkan banyak pengujian gagal.
Salah satu solusinya adalah membagi rangkaian pengujian. Kami akan keluar
BlogPage.test.js
dan membuat yang baru PostContent.test.js
yang seharusnya berisi tes khusus untuk PostContent
. Ide dasarnya adalah bahwa fungsi apa pun yang ditempatkan di PostContent
harus ditentukan PostContent.test.js
, dan fungsi apa pun yang ditempatkan di BlogPage
(seperti penguraian URL) harus dalam BlogPage.test.js
.
Baik.
Tapi bagaimana jika rendering
PostContent
memiliki efek samping?
export const PostContent = ({ id }) => {
const [ text, setText ] = useState("")
useEffect(() => {
fetchPostContent(id)
}, [id])
const fetchPostContent = async () => {
const result = await fetch(`/post?id=${id}`)
if (result.ok) {
setText(await result.text())
}
}
return <p>{text}</p>
};
Rangkaian pengujian
BlogPage.test.js
harus menyadari efek sampingnya dan bersiap untuk menanganinya. Misalnya, dia harus menyiapkan fetch
jawaban.
Ketergantungan yang kami coba hindari dengan memisahkan rangkaian pengujian kami masih ada.
Pengaturan pengujian kami sudah pasti menjadi lebih baik, tetapi pada akhirnya, tidak ada yang terjadi untuk membuat pengujian kami kurang rapuh.
Untuk ini kita membutuhkan rintisan (atau tiruan)
PostContent
.
Dan di bagian selanjutnya kita akan melihat bagaimana melakukan ini.
Apakah ini benar-benar perlu?
Ngomong-ngomong, beberapa kata tentang berpindah dari pengujian ujung ke ujung ke pengujian unit.
Memiliki tes ganda adalah indikator kunci bahwa Anda menulis tes unit.
Banyak penguji berpengalaman memulai proyek baru segera dengan pengujian unit (dan mengejek) karena mereka tahu bahwa saat basis kode mereka berkembang, mereka akan mengalami masalah ketidakstabilan pengujian.
Tes unit biasanya jauh lebih kecil daripada tes ujung ke ujung. Mereka bisa jadi sangat kecil sehingga seringkali tidak lebih dari tiga atau empat baris kode. Ini menjadikan mereka kandidat yang bagus untuk praktik pengkodean sosial seperti pemasangan dan pemrograman ensemble.
Bahkan ketika kami melakukan pengujian unit, pengujian ganda tidak selalu diperlukan - mereka hanyalah alat lain di suite Anda yang perlu Anda ketahui kapan dan bagaimana menerapkannya.
Di bagian selanjutnya, kita akan membahas teknik-teknik dasar mengejek .