Apa yang saya sukai dari ekosistem Bereaksi adalah bahwa banyak IDEAS berada di belakang banyak keputusan. Berbagai penulis menulis berbagai artikel untuk mendukung tatanan yang ada dan menjelaskan mengapa semuanya "benar", sehingga semua orang mengerti bahwa partai berada di jalur yang benar.
Setelah beberapa waktu, IDEA berubah sedikit, dan semuanya dimulai dari awal.
Dan awal cerita ini adalah pemisahan komponen menjadi Kontainer dan non-Kontainer (populer disebut Komponen Bodoh, maaf untuk bahasa Prancis saya).

Masalah
Masalahnya sangat sederhana - unit test. Baru-baru ini, ada beberapa gerakan menuju tes integrasi - yah, Anda tahu "Tulis tes. Tidak terlalu banyak. Sebagian besar integrasi." . Ini bukan ide yang buruk, dan jika waktunya singkat (dan tes tidak terlalu dibutuhkan) - inilah yang perlu Anda lakukan. Anggap saja ini tes asap - untuk memverifikasi bahwa sepertinya tidak ada yang meledak.
Jika ada banyak waktu, dan tes diperlukan, lebih baik tidak pergi dengan cara ini, karena menulis tes integrasi yang baik sangat, sangat lama. Hanya karena mereka akan tumbuh dan berkembang, dan untuk menguji tombol ketiga di sebelah kanan, Anda harus terlebih dahulu mengklik 3 tombol di menu, dan jangan lupa untuk login. Secara umum - inilah ledakan kombinatorial pada plat perak.
Solusi di sini adalah satu dan sederhana (menurut definisi) - tes unit. Kemampuan untuk memulai tes dengan beberapa keadaan sudah siap dari beberapa bagian aplikasi. Lebih tepatnya, untuk mengurangi (mempersempit) area pengujian dari Aplikasi atau Blok Besar menjadi sesuatu yang kecil - sebuah unit, tidak peduli apa itu. Tidak perlu menggunakan enzim - Anda dapat menjalankan tes browser, jika jiwa bertanya. Yang paling penting di sini adalah untuk dapat menguji sesuatu secara terpisah . Dan tanpa terlalu banyak kesulitan.
Isolasi adalah salah satu poin kunci dalam pengujian unit, dan itulah sebabnya unit test tidak suka. Mereka tidak menyukainya karena berbagai alasan:
- misalnya, "unit" Anda terlepas dari aplikasi, dan tidak berfungsi dalam komposisinya bahkan ketika tesnya sendiri berwarna hijau.
- atau misalnya karena isolasi adalah kuda bulat dalam kekosongan yang belum pernah dilihat siapa pun. Bagaimana cara mencapainya, dan bagaimana mengukurnya?
Secara pribadi, saya tidak melihat masalah di sini. Di paragraf pertama, tentu saja, Anda dapat merekomendasikan tes integrasi, mereka telah diciptakan untuk itu - untuk memeriksa bagaimana komponen pra-diuji dipasang dengan benar. Anda mempercayai paket npm yang menguji, tentu saja, hanya diri mereka sendiri, dan bukan diri mereka sendiri sebagai bagian dari aplikasi Anda. Apa perbedaan βkomponenβ Anda dengan paket βbukan Andaβ?
Dengan paragraf kedua, semuanya sedikit lebih rumit. Dan artikel ini akan persis tentang hal ini (dan semuanya sebelum itu - pengantar) - tentang bagaimana membuat unit " unit " dapat diuji .
Bagilah dan Taklukkan
Gagasan memisahkan komponen Bereaksi menjadi "Wadah" dan "Presentasi" bukanlah hal baru, dijelaskan dengan baik, dan telah berhasil menjadi sedikit ketinggalan jaman. Jika kita mengambil sebagai dasar (apa yang dilakukan 99% pengembang) sebuah artikel oleh Dan Abramov , maka Komponen Presentasi:
- Khawatir dengan bagaimana hal-hal terlihat
- Dapat mengandung komponen presentasi dan wadah
**
di dalam, dan biasanya memiliki beberapa markup DOM dan gaya mereka sendiri) - Slot dukungan (Sering memungkinkan penahanan melalui this.props.children)
- Aplikasi independen (Tidak memiliki ketergantungan pada sisa aplikasi, seperti tindakan Flux atau toko)
- Jangan bergantung pada data (Jangan tentukan bagaimana data dimuat atau dimutasi)
- Antarmuka didasarkan pada alat peraga (Menerima data dan panggilan balik secara eksklusif melalui alat peraga)
- Seringkali tanpa kewarganegaraan (Jarang memiliki status mereka sendiri (ketika mereka melakukannya, ini adalah keadaan UI daripada data))
- Seringkali SFC (Ditulis sebagai komponen fungsional kecuali mereka membutuhkan status, pengait siklus hidup, atau optimalisasi kinerja)
Nah, Wadah semuanya adalah logika, semua akses ke data, dan seluruh aplikasi pada prinsipnya.
Dalam dunia yang ideal, wadah adalah bagasi, dan komponen presentasi adalah dedaunan.
Ada dua poin utama dalam definisi Dan: "Aplikasi independen" , yang hampir merupakan definisi akademis tentang "unit", dan * "Dapat berisi komponen presentasi dan wadah **
" *, di mana bintang-bintang ini sangat menarik.
(terjemahan gratis) ** Dalam versi awal artikel saya, saya (Dan) mengatakan bahwa komponen presentasi hanya boleh mengandung komponen presentasi lainnya. Saya tidak berpikir begitu lagi. Jenis komponen adalah perincian dan dapat berubah seiring waktu. Secara umum, jangan bagikan dan semuanya akan baik-baik saja.
Mari kita ingat apa yang terjadi setelah ini:
- Dalam buku cerita, semuanya jatuh, karena semacam wadah, di tombol ketiga di sebelah kiri, merangkak ke sisi yang tidak ada. Salam khusus untuk graphql, react-router dan lainnya react-intl.
- Kemampuan untuk menggunakan mount dalam tes hilang, karena itu membuat semuanya dari A ke Z, dan sekali lagi, di suatu tempat di kedalaman pohon render, seseorang melakukan sesuatu, dan tes jatuh.
- Kemampuan untuk mengontrol status aplikasi hilang, karena (secara kiasan), kemampuan untuk membasahi pemilih / penyelesai (terutama dengan proxyquire) hilang, dan seluruh sisi harus basah. Dan ini keren untuk unit test.
Jika Anda berpikir bahwa masalahnya sedikit dibikin - coba bekerja dalam tim ketika wadah ini, yang akan digunakan dalam non-wadah Anda, berubah di departemen lain, dan sebagai hasilnya, Anda dan mereka melihat tes dan Anda tidak dapat memahami mengapa kemarin semuanya itu berhasil, dan sekarang lagi.
Akibatnya, Anda harus menggunakan dangkal, yang dengan desain menghilangkan semua efek samping yang berbahaya (dan tidak terduga). Berikut adalah contoh sederhana dari artikel "Mengapa saya selalu menggunakan dangkal"
Bayangkan Tooltip itu merender "?", Ketika diklik, tipe itu sendiri akan ditampilkan.
import Tooltip from 'react-cool-tooltip'; const MyComponent = () => { <Tooltip> hint: {veryImportantTextYouHaveToTest} </Tooltip> }
Bagaimana cara mengujinya? Pasang + klik + periksa apa yang terlihat. Ini adalah tes integrasi, bukan unit, dan pertanyaannya adalah bagaimana mengklik komponen "asing" untuk Anda. Tidak ada masalah dengan dangkal, karena tidak ada otak dan "komponen alien" itu sendiri. Tetapi ada otak di sini, karena Tooltip adalah wadah, sementara MyComponent praktis presentasi.
jest.mock('react-cool-tooltip', {default: ({children}) => childlren});
Tetapi jika Anda bereaksi-cool-tooltip, maka tidak akan ada masalah dengan pengujian. "Komponen" telah menjadi sangat banyak, lebih pendek, lebih terbatas .
Komponen terakhir
- komponen dengan ukuran terkenal, yang mungkin termasuk komponen final lainnya yang diketahui sebelumnya, atau tidak mengandungnya sama sekali.
- tidak mengandung wadah lain, karena mengandung keadaan yang tidak terkendali dan ukuran "naik", mis. membuat komponen saat ini tidak terbatas .
- kalau tidak itu adalah komponen presentasi biasa. Bahkan, persis seperti yang dijelaskan dalam versi pertama artikel Dan.
Komponen terakhir hanyalah gear yang diambil dari mekanisme besar.
Seluruh pertanyaannya adalah bagaimana cara mengeluarkannya.
Solusi 1 - DI
Favorit saya adalah Injeksi Ketergantungan. Dan juga mencintainya . Secara umum, ini bukan DI, tetapi "slot". Singkatnya - tidak perlu menggunakan Kontainer di dalam Presentasi - mereka harus disuntikkan di sana. Dan dalam tes akan mungkin untuk menyuntikkan sesuatu yang lain.
Ini persis seperti ketika "kontainer adalah bagasi, dan komponen presentasi adalah daun"
Solusi 2 - Batas
DI sering kali bisa keren. Mungkin sekarang% nama pengguna% berpikir bagaimana ini dapat diterapkan pada basis kode saat ini, dan solusinya tidak ditemukan ...
Dalam kasus seperti itu, Perbatasan akan menyelamatkan Anda.
const Boundary = ({children}) => ( process.env.NODE_ENV === 'test' ? null : children
Di sini, alih-alih "slot," semua "titik transisi" hanya berubah menjadi Batas, yang akan membuat apa pun selama pengujian. Cukup deklaratif , dan persis apa yang Anda butuhkan untuk "mengambil gigi."
Solusi 3 - Tingkat
Perbatasan bisa sedikit kasar, dan mungkin lebih mudah untuk membuatnya sedikit lebih pintar dengan menambahkan sedikit pengetahuan tentang Layer.
const checkTier = tier => tier === currentTier; const withTier = tier => WrapperComponent => (props) => ( (process.env.NODE_ENV !== 'test' || checkTier(tier)) && <WrapperComponent{...props} /> ); const PageChrome = () => ( <section> <aside><ASideContainer /></aside> <Page /> </section> ); const ASideContainer = withTier('UI')(...) const Page = withTier('Page')(...) const PageChromeContainer = withTier('UI')(PageChrome);
Di bawah nama Tier / Layer, bisa ada hal yang berbeda - fitur, bebek, modul, atau hanya layer / tier itu. Intinya tidak penting, yang utama adalah Anda dapat menarik persneling, mungkin bukan satu, tetapi angka terakhir, entah bagaimana menarik garis antara apa yang Anda butuhkan dan apa yang tidak Anda butuhkan (untuk tes yang berbeda ini adalah perbatasan yang berbeda).
Dan tidak ada yang mencegah menandai batas-batas ini dengan cara yang berbeda.
Solusi 4 - Kekhawatiran Terpisah
Jika solusinya (menurut definisi) terletak pada pemisahan entitas - apa yang akan terjadi jika kita mengambil dan memisahkannya?
"Wadah," yang sangat tidak kita sukai, biasanya disebut wadah . Dan jika tidak - tidak ada yang mencegah sekarang mulai memberi nama Components entah bagaimana lebih nyaring. Atau mereka memiliki pola tertentu dalam namanya - Connect (WrappedComonent), atau GraphQL / Query.
Bagaimana jika hak dalam runtime menarik garis antara entitas berdasarkan nama?
const PageChrome = () => ( <section> <aside><ASideContainer /></aside> <Page /> </section> );
Ditambah satu baris dalam pengujian, dan reaksi ulang akan menghapus semua wadah yang dapat mengganggu tes.
Pada prinsipnya, pendekatan ini dapat digunakan untuk menguji wadah itu sendiri - Anda hanya perlu menghapus semuanya kecuali wadah pertama.
import {createElement, remock} from 'react-remock';
Sekali lagi - beberapa garis dan gigi dilepas.
Total
Selama setahun terakhir, pengujian komponen Bereaksi menjadi lebih rumit, terutama untuk pemasangan - Anda perlu menimpa semua 10 Penyedia, Konteks, dan semakin sulit untuk menguji komponen yang tepat dalam gaya yang tepat - ada terlalu banyak tali untuk ditarik.
Seseorang meludah dan pergi ke dunia yang dangkal. Seseorang melambaikan tangan pada unit test dan memindahkan semuanya ke Cypress (berjalan seperti berjalan!).
Seseorang menusuk jari di reaksi, mengatakan bahwa ini adalah efek aljabar dan Anda dapat melakukan apa pun yang Anda inginkan. Semua contoh di atas pada dasarnya adalah penggunaan efek dan ejekan aljabar ini. Bagi saya dan DI ini adalah moki.
PS: Posting ini ditulis sebagai tanggapan terhadap komentar dalam React / RFC tentang fakta bahwa tim React memecahkan segalanya, dan semua polimer di sana juga
PPS: Posting ini sebenarnya adalah terjemahan lain yang sangat gratis
PPPS: Secara umum, untuk isolasi nyata, lihat rewiremock