Saya menggunakan mocha untuk menguji unit aplikasi yang ditulis untuk node.js
Saya ingin tahu apakah mungkin untuk menguji fungsi unit yang belum diekspor dalam sebuah modul.
Contoh:
Saya memiliki banyak fungsi yang didefinisikan seperti ini di foobar.js
function private_foobar1(){
...
}
function private_foobar2(){
...
}
dan beberapa fungsi yang diekspor sebagai publik:
exports.public_foobar3 = function(){
...
}
Test case disusun sebagai berikut:
describe("private_foobar1", function() {
it("should do stuff", function(done) {
var stuff = foobar.private_foobar1(filter);
should(stuff).be.ok;
should(stuff).....
Jelas ini tidak berfungsi, karena private_foobar1
tidak diekspor.
Apa cara yang benar untuk menguji metode pribadi unit? Apakah moka memiliki beberapa metode bawaan untuk melakukan itu?
Jawaban:
Jika fungsi tidak diekspor oleh modul, itu tidak dapat dipanggil dengan kode uji di luar modul. Itu karena cara kerja JavaScript, dan Mocha tidak dapat dengan sendirinya mengelak dari ini.
Dalam beberapa kasus di mana saya menentukan bahwa pengujian fungsi pribadi adalah hal yang benar untuk dilakukan, apa yang telah saya lakukan adalah mengatur beberapa variabel lingkungan yang diperiksa modul saya untuk menentukan apakah itu berjalan dalam pengaturan pengujian atau tidak. Jika itu berjalan dalam pengaturan pengujian, maka itu mengekspor fungsi tambahan yang kemudian dapat saya panggil selama pengujian.
Kata "lingkungan" digunakan secara longgar di sini. Ini mungkin berarti memeriksa
process.env
atau sesuatu yang lain yang dapat berkomunikasi dengan modul "Anda sedang diuji sekarang". Contoh di mana saya harus melakukan ini berada dalam lingkungan RequireJS, dan saya telah menggunakanmodule.config
untuk tujuan ini.sumber
SyntaxError: 'import' and 'export' may only appear at the top level
import
,export
di dalam blok. Akhirnya Anda akan dapat mencapai hal semacam ini di ES6 dengan System loader. Salah satu cara untuk menyiasatinya sekarang adalah dengan menggunakanmodule.exports = process.env.NODE_ENV === 'production' ? require('prod.js') : require('dev.js')
dan menyimpan perbedaan kode ES6 Anda di file masing-masing.Lihat modul rewire . Ini memungkinkan Anda untuk mendapatkan (dan memanipulasi) variabel dan fungsi pribadi dalam suatu modul.
Jadi dalam kasus Anda penggunaannya akan seperti:
sumber
Cannot find module '../../package' from 'node.js'
. Adakah yang akrab dengan ini?.ts
,typescript
saya menjalankan menggunakants-node
@cluBerikut ini adalah alur kerja yang sangat bagus untuk menguji metode pribadi Anda yang dijelaskan oleh Philip Walton, seorang insinyur Google di blog-nya.
Prinsip
_
contohKemudian gunakan tugas build atau sistem build Anda sendiri (untuk contoh grunt-strip-code) untuk menghapus blok ini untuk build produksi.
Build pengujian Anda memiliki akses ke api pribadi Anda, dan build produksi Anda belum.
Potongan
Tulis kode Anda seperti ini:
Dan tugas kasarmu seperti itu
Lebih dalam
Dalam artikel selanjutnya , ini menjelaskan "mengapa" dari "pengujian metode pribadi"
sumber
Jika Anda lebih suka membuatnya sederhana, cukup ekspor anggota pribadi juga, tetapi jelas dipisahkan dari API publik dengan beberapa konvensi, misalnya awali mereka dengan
_
atau sarang mereka di bawah satu objek pribadi .sumber
Saya membuat paket npm untuk tujuan ini yang mungkin berguna bagi Anda: memerlukan-dari
Pada dasarnya Anda mengekspos metode non-publik dengan:
catatan:
testExports
dapat berupa nama valid yang Anda inginkan, kecualiexports
tentu saja.Dan dari modul lain:
sumber
requireFrom
dengan parameter yang tepat.) Juga, jika modul dengantextExports
dimuat olehrequire
panggilan sebelumrequireFrom
memuatnya,requireFrom
akan kembaliundefined
. (Saya baru saja mengujinya.) Meskipun seringkali dimungkinkan untuk mengontrol urutan muatan modul, itu tidak selalu praktis. (Sebagaimana dibuktikan oleh beberapa pertanyaan Mocha pada SO.) Solusi ini juga umumnya tidak akan bekerja dengan modul tipe AMD. (Saya memuat modul AMD di Node setiap hari untuk pengujian.)Saya telah menambahkan fungsi tambahan yang saya beri nama Internal () dan mengembalikan semua fungsi pribadi dari sana. Ini internal () function kemudian diekspor. Contoh:
Anda dapat memanggil fungsi internal seperti ini:
Saya suka solusi ini karena:
sumber
Saya mengikuti jawaban @barwin dan memeriksa bagaimana tes unit dapat dilakukan dengan modul rewire . Saya dapat mengkonfirmasi bahwa solusi ini hanya berfungsi.
Modul harus diminta dalam dua bagian - bagian publik dan bagian pribadi. Untuk fungsi publik, Anda dapat melakukannya dengan cara standar:
Untuk ruang lingkup pribadi:
Untuk mengetahui lebih banyak tentang subjek, saya membuat contoh kerja dengan pengujian modul lengkap, pengujian mencakup ruang lingkup pribadi dan publik.
Untuk informasi lebih lanjut, saya mendorong Anda untuk memeriksa artikel ( https://medium.com/@macsikora/how-to-test-private-functions-of-es6-module-fb8c1345b25f ) yang sepenuhnya menggambarkan subjek, termasuk contoh kode.
sumber
Saya tahu bahwa ini belum tentu jawaban yang Anda cari, tetapi apa yang saya temukan adalah bahwa sebagian besar waktu jika fungsi pribadi layak diuji, ada baiknya berada di file sendiri.
Misalnya alih-alih memiliki metode pribadi dalam file yang sama dengan yang publik, seperti ini ...
src / hal / PublicInterface.js
... Anda membaginya seperti ini:
src / hal / PublicInterface.js
src / hal / internal / helper1.js
src / hal / internal / helper2.js
Dengan begitu, Anda dapat dengan mudah menguji
helper1
danhelper2
apa adanya, tanpa menggunakan Rewire dan "sihir" lainnya (yang, saya temukan, memiliki poin rasa sakitnya sendiri saat debugging, atau ketika Anda mencoba untuk bergerak menuju TypeScript, belum lagi lebih miskin dimengerti untuk kolega baru). Dan mereka yang berada di sub-folder bernamainternal
, atau sesuatu seperti itu, akan membantu menghindari penggunaan mereka secara tidak sengaja di tempat yang tidak diinginkan.PS: Masalah umum lainnya dengan metode "pribadi" adalah bahwa jika Anda ingin menguji
publicMethod1
danpublicMethod2
dan mengejek pembantu, sekali lagi, Anda biasanya perlu sesuatu seperti Rewire untuk melakukan itu. Namun, jika mereka berada di file terpisah, Anda dapat menggunakan Proxyquire untuk melakukannya, yang, tidak seperti Rewire, tidak memerlukan perubahan apa pun pada proses pembuatan Anda, mudah dibaca dan di-debug, dan berfungsi dengan baik bahkan dengan TypeScript.sumber
Untuk membuat metode pribadi tersedia untuk pengujian, saya melakukan ini:
sumber