Bagaimana Anda menguji fungsi pribadi di sudut 2?
class FooBar {
private _status: number;
constructor( private foo : Bar ) {
this.initFooBar();
}
private initFooBar(){
this.foo.bar( "data" );
this._status = this.fooo.foo();
}
public get status(){
return this._status;
}
}
Solusi yang saya temukan
Letakkan kode tes itu sendiri di dalam penutupan atau Tambahkan kode di dalam penutupan yang menyimpan referensi ke variabel lokal pada objek yang ada di lingkup luar.
Kemudian hapus kode uji menggunakan alat. http://philipwalton.com/articles/how-to-unit-test-private-functions-in-javascript/
Tolong sarankan saya cara yang lebih baik untuk menyelesaikan masalah ini jika Anda telah melakukan apa pun?
PS
Sebagian besar jawaban untuk jenis pertanyaan serupa seperti ini tidak memberikan solusi untuk masalah, itu sebabnya saya menanyakan pertanyaan ini
Sebagian besar pengembang mengatakan Anda Jangan menguji fungsi pribadi tetapi saya tidak mengatakan mereka salah atau benar, tetapi ada kebutuhan untuk kasus saya untuk menguji pribadi.
sumber
Jawaban:
Saya bersama Anda, meskipun itu adalah tujuan yang baik untuk "hanya menguji unit API publik" ada kalanya tampaknya tidak sesederhana itu dan Anda merasa Anda memilih antara mengkompromikan API atau unit-test. Anda sudah tahu ini, karena itulah yang ingin Anda lakukan, jadi saya tidak akan membahasnya. :)
Di TypeScript saya telah menemukan beberapa cara Anda dapat mengakses anggota pribadi demi pengujian unit. Pertimbangkan kelas ini:
Meskipun akses TS Membatasi kepada anggota kelas menggunakan
private
,protected
,public
, yang disusun JS tidak memiliki anggota pribadi, karena ini bukan hal yang di JS. Ini murni digunakan untuk kompiler TS. Untuk itu:Anda dapat menegaskan
any
dan keluar dari kompiler agar tidak memperingatkan Anda tentang batasan akses:Masalah dengan pendekatan ini adalah bahwa kompiler tidak tahu apa yang Anda lakukan dengan benar
any
, sehingga Anda tidak mendapatkan kesalahan tipe yang diinginkan:Ini jelas akan membuat refactoring lebih sulit.
Anda dapat menggunakan akses array (
[]
) untuk mendapatkan anggota pribadi:Meskipun terlihat funky, TSC sebenarnya akan memvalidasi jenis-jenisnya seolah-olah Anda mengaksesnya secara langsung:
Sejujurnya saya tidak tahu mengapa ini berhasil.Ini tampaknya merupakan "pintu keluar" yang disengaja untuk memberi Anda akses ke anggota pribadi tanpa kehilangan jenis keamanan. Ini persis seperti yang saya pikir Anda inginkan untuk pengujian unit Anda.Berikut ini adalah contoh yang berfungsi di TypeScript Playground .
Edit untuk TypeScript 2.6
Opsi lain yang beberapa suka adalah menggunakan
// @ts-ignore
( ditambahkan pada TS 2.6 ) yang hanya menekan semua kesalahan pada baris berikut:Masalah dengan ini adalah, yah, itu menekan semua kesalahan pada baris berikut:
Saya pribadi mempertimbangkan
@ts-ignore
bau kode, dan seperti yang dikatakan oleh para dokter:sumber
as any
: Anda kehilangan semua pemeriksaan jenis.Anda dapat memanggil metode pribadi . Jika Anda mengalami kesalahan berikut:
cukup gunakan
// @ts-ignore
:sumber
as any
Anda kehilangan pemeriksaan jenis, sebenarnya Anda kehilangan pemeriksaan jenis di seluruh baris.Karena sebagian besar pengembang tidak merekomendasikan pengujian fungsi pribadi , Mengapa tidak mengujinya ?.
Misalnya.
YourClass.ts
TestYourClass.spec.ts
Terima kasih kepada @ Harun, @Thierry Templier.
sumber
Jangan menulis tes untuk metode pribadi. Ini mengalahkan titik tes unit.
Contoh
Tes untuk metode ini seharusnya tidak perlu berubah jika nanti implementasinya berubah tetapi
behaviour
API publik tetap sama.Jangan membuat metode dan properti menjadi publik hanya untuk mengujinya. Ini biasanya berarti bahwa:
sumber
Inti dari "jangan menguji metode pribadi" sebenarnya adalah Menguji kelas seperti seseorang yang menggunakannya .
Jika Anda memiliki API publik dengan 5 metode, konsumen kelas Anda dapat menggunakannya, dan karenanya Anda harus mengujinya. Seorang konsumen tidak boleh mengakses metode / properti pribadi kelas Anda, yang berarti Anda dapat mengubah anggota pribadi ketika fungsi publik yang terbuka tetap sama.
Jika Anda mengandalkan fungsionalitas ekstensible internal, gunakan
protected
sebagai gantiprivate
.Perhatikan bahwa
protected
ini masih API publik (!) , Hanya digunakan secara berbeda.Uji unit properti yang dilindungi dengan cara yang sama seperti konsumen akan menggunakannya, melalui subklas:
sumber
Ini bekerja untuk saya:
Dari pada:
Ini:
sumber
Maaf untuk necro di posting ini, tapi saya merasa harus mempertimbangkan beberapa hal yang tampaknya belum disentuh.
Pertama yang terpenting - ketika kita menemukan diri kita membutuhkan akses ke anggota pribadi di kelas selama pengujian unit, umumnya merupakan bendera merah besar dan gemuk yang telah kita abaikan dalam pendekatan strategis atau taktis kita dan secara tidak sengaja telah melanggar prinsip tanggung jawab tunggal dengan mendorong perilaku di tempat yang tidak seharusnya. Merasakan perlunya mengakses metode yang benar-benar tidak lebih dari subrutin terisolasi dari prosedur konstruksi adalah salah satu kejadian paling umum dari ini; Namun, ini seperti bos Anda yang mengharapkan Anda datang ke tempat kerja siap-pergi dan juga memiliki beberapa kebutuhan buruk untuk mengetahui rutinitas pagi apa yang Anda lalui untuk membawa Anda ke keadaan itu ...
Contoh paling umum lainnya dari kejadian ini adalah ketika Anda mencoba menguji "kelas dewa" pepatah. Ini adalah jenis masalah khusus di dalam dan dari dirinya sendiri, tetapi menderita dari masalah dasar yang sama dengan perlu mengetahui detail intim dari suatu prosedur - tapi itu keluar dari topik.
Dalam contoh khusus ini, kami telah secara efektif menetapkan tanggung jawab menginisialisasi sepenuhnya objek Bar ke konstruktor kelas FooBar. Dalam pemrograman berorientasi objek, salah satu penyewa inti adalah bahwa konstruktornya "sakral" dan harus dijaga terhadap data yang tidak valid yang akan membuat keadaan internal tidak valid dan membiarkannya gagal di tempat lain di hilir (dalam apa yang bisa menjadi sangat dalam) pipa.)
Kami gagal melakukannya di sini dengan mengizinkan objek FooBar menerima Bilah yang belum siap pada saat FooBar dibangun, dan telah mengompensasi dengan semacam "peretasan" objek FooBar untuk mengambil masalah menjadi miliknya sendiri tangan.
Ini adalah hasil dari kegagalan untuk mematuhi penyewa lain pemrograman berorientasi objek (dalam kasus Bar,) yang menyatakan bahwa keadaan objek harus sepenuhnya diinisialisasi dan siap untuk menangani panggilan masuk apa pun ke anggota publiknya segera setelah pembuatan. Sekarang, ini tidak berarti segera setelah konstruktor dipanggil dalam semua contoh. Ketika Anda memiliki objek yang memiliki banyak skenario konstruksi kompleks, maka lebih baik untuk mengekspos setter ke anggota opsionalnya ke objek yang diimplementasikan sesuai dengan pola desain-penciptaan (Pabrik, Pembangun, dll ...) Di salah satu kasus terakhir,
Dalam contoh Anda, properti "status" Bar tampaknya tidak dalam keadaan valid di mana FooBar dapat menerimanya - sehingga FooBar melakukan sesuatu untuk memperbaikinya.
Masalah kedua yang saya lihat adalah tampaknya Anda mencoba menguji kode Anda daripada mempraktikkan pengembangan yang digerakkan oleh tes. Ini jelas merupakan pendapat saya sendiri pada saat ini; tetapi, jenis pengujian ini benar-benar anti-pola. Apa yang akhirnya Anda lakukan adalah jatuh ke dalam perangkap menyadari bahwa Anda memiliki masalah desain inti yang mencegah kode Anda dari diuji setelah fakta, daripada menulis tes yang Anda butuhkan dan kemudian pemrograman untuk tes. Apa pun masalah yang Anda hadapi, Anda masih harus berakhir dengan jumlah tes dan jalur kode yang sama jika Anda benar-benar mencapai implementasi SOLID. Jadi - mengapa mencoba dan merekayasa balik jalan Anda menjadi kode yang dapat diuji ketika Anda bisa mengatasi masalah tersebut saat upaya pengembangan Anda dimulai?
Seandainya Anda melakukan itu, maka Anda akan menyadari jauh sebelumnya bahwa Anda harus menulis beberapa kode yang agak menjengkelkan untuk menguji desain Anda dan akan memiliki kesempatan sejak awal untuk menyelaraskan kembali pendekatan Anda dengan mengubah perilaku menjadi implementasi yang mudah diuji.
sumber
Saya setuju dengan @toskv: Saya tidak akan merekomendasikan untuk melakukan itu :-)
Tetapi jika Anda benar-benar ingin menguji metode pribadi Anda, Anda dapat menyadari bahwa kode yang sesuai untuk TypeScript sesuai dengan metode prototipe fungsi konstruktor. Ini berarti dapat digunakan saat runtime (padahal Anda mungkin akan memiliki beberapa kesalahan kompilasi).
Sebagai contoh:
akan diubah menjadi:
Lihat plunkr ini: https://plnkr.co/edit/calJCF?p=preview .
sumber
Seperti yang telah banyak dinyatakan, sebanyak Anda ingin menguji metode pribadi Anda tidak harus meretas kode atau transpiler Anda untuk membuatnya bekerja untuk Anda. TypeScript modern akan menolak sebagian besar peretasan yang telah disediakan orang sejauh ini.
Larutan
TLDR ; jika suatu metode harus diuji maka Anda harus memisahkan kode ke dalam kelas yang Anda dapat mengekspos metode tersebut untuk umum untuk diuji.
Alasan Anda memiliki metode privat adalah karena fungsionalitas tidak harus menjadi milik diekspos oleh kelas itu, dan oleh karena itu jika fungsionalitas tidak termasuk di sana itu harus dipisahkan ke dalam kelas itu sendiri.
Contoh
Saya membaca artikel ini yang menjelaskan cara Anda menangani metode pribadi. Bahkan mencakup beberapa metode di sini dan bagaimana mengapa itu implementasi yang buruk.
https://patrickdesjardins.com/blog/how-to-unit-test-private-method-in-typescript-part-2
Catatan : Kode ini diambil dari blog yang ditautkan di atas (Saya menduplikasi jika konten di balik tautan berubah)
Sebelum Setelahsumber
panggil metode pribadi menggunakan tanda kurung
File ts
file spect.ts
sumber
Jawaban oleh Aaron adalah yang terbaik dan bekerja untuk saya :) Saya akan memilihnya tetapi sayangnya saya tidak bisa (kehilangan reputasi).
Saya harus mengatakan pengujian metode pribadi adalah satu-satunya cara untuk menggunakannya dan memiliki kode bersih di sisi lain.
Sebagai contoh:
Sangat masuk akal untuk tidak menguji semua metode ini sekaligus karena kita perlu mencemooh metode pribadi itu, yang tidak dapat kita tiru karena kita tidak dapat mengaksesnya. Ini berarti kita membutuhkan banyak konfigurasi untuk pengujian unit untuk menguji ini secara keseluruhan.
Ini mengatakan cara terbaik untuk menguji metode di atas dengan semua dependensi adalah tes ujung ke ujung, karena di sini tes integrasi diperlukan, tetapi tes E2E tidak akan membantu Anda jika Anda berlatih TDD (Test Driven Development), tetapi pengujian metode apa pun akan.
sumber
Rute ini saya ambil adalah salah satu tempat saya membuat fungsi di luar kelas dan menetapkan fungsi ke metode pribadi saya.
Sekarang saya tidak tahu apa jenis aturan OOP yang saya langgar, tetapi untuk menjawab pertanyaan, ini adalah cara saya menguji metode pribadi. Saya menyambut siapa pun untuk memberi nasihat tentang Pro & Kontra ini.
sumber