Saya menemukan diskusi tentang Apakah Anda menguji metode pribadi informatif.
Saya telah memutuskan, bahwa di beberapa kelas, saya ingin memiliki metode yang dilindungi, tetapi mengujinya. Beberapa metode ini statis dan pendek. Karena sebagian besar metode publik memanfaatkannya, saya mungkin akan dapat dengan aman menghapus tes nanti. Tetapi untuk memulai dengan pendekatan TDD dan menghindari debugging, saya benar-benar ingin mengujinya.
Saya memikirkan hal berikut:
- Metode Obyek seperti yang disarankan dalam jawaban tampaknya terlalu banyak untuk ini.
- Mulailah dengan metode publik dan ketika cakupan kode diberikan oleh tes tingkat yang lebih tinggi, jadikan kode tersebut terlindungi dan hapus tes.
- Mewarisi kelas dengan antarmuka yang dapat diuji membuat metode yang dilindungi publik
Yang merupakan praktik terbaik? Apakah ada hal lain?
Tampaknya, JUnit secara otomatis mengubah metode yang dilindungi menjadi publik, tapi saya tidak melihatnya lebih dalam. PHP tidak mengizinkan ini melalui refleksi .
php
unit-testing
phpunit
GrGr
sumber
sumber
Jawaban:
Jika Anda menggunakan PHP5 (> = 5.3.2) dengan PHPUnit, Anda dapat menguji metode pribadi dan terlindungi dengan menggunakan refleksi untuk mengaturnya agar publik sebelum menjalankan tes Anda:
sumber
protected
metode juga merupakan bagian dari api publik karena setiap kelas pihak ketiga dapat memperluas dan menggunakannya tanpa sihir. Jadi saya pikir hanyaprivate
metode yang masuk dalam kategori metode yang tidak akan diuji secara langsung.protected
danpublic
harus langsung diuji.Kamu sepertinya sudah sadar, tapi aku akan menyatakannya kembali; Ini pertanda buruk, jika Anda perlu menguji metode yang dilindungi. Tujuan dari tes unit, adalah untuk menguji antarmuka kelas, dan metode yang dilindungi adalah detail implementasi. Yang mengatakan, ada kasus di mana itu masuk akal. Jika Anda menggunakan warisan, Anda dapat melihat superclass sebagai menyediakan antarmuka untuk subkelas. Jadi di sini, Anda harus menguji metode yang dilindungi (Tapi tidak pernah metode pribadi ). Solusi untuk ini, adalah membuat subclass untuk tujuan pengujian, dan menggunakannya untuk mengekspos metode. Misalnya.:
Perhatikan bahwa Anda selalu dapat mengganti warisan dengan komposisi. Saat menguji kode, biasanya jauh lebih mudah untuk berurusan dengan kode yang menggunakan pola ini, jadi Anda mungkin ingin mempertimbangkan opsi itu.
sumber
teastburn memiliki pendekatan yang tepat. Lebih sederhana lagi adalah dengan memanggil metode secara langsung dan mengembalikan jawabannya:
Anda dapat memanggil ini hanya dalam tes Anda dengan:
sumber
Saya ingin mengusulkan sedikit variasi untuk getMethod () didefinisikan dalam jawaban uckelman .
Versi ini mengubah getMethod () dengan menghapus nilai-nilai hard-coded dan menyederhanakan penggunaan sedikit. Saya sarankan menambahkannya ke kelas PHPUnitUtil Anda seperti pada contoh di bawah ini atau ke PHPUnit_Framework_TestCase-kelas perluasan Anda (atau, saya kira, secara global ke file PHPUnitUtil Anda).
Sejak MyClass sedang instantiated lagian dan ReflectionClass dapat mengambil string atau objek ...
Saya juga membuat fungsi alias getProtectedMethod () untuk menjadi eksplisit apa yang diharapkan, tetapi itu terserah Anda.
Bersulang!
sumber
Saya pikir troelskn dekat. Saya akan melakukan ini sebagai gantinya:
Kemudian, terapkan sesuatu seperti ini:
Anda kemudian menjalankan tes Anda terhadap TestClassToTest.
Seharusnya dimungkinkan untuk secara otomatis menghasilkan kelas ekstensi tersebut dengan menguraikan kode. Saya tidak akan terkejut jika PHPUnit sudah menawarkan mekanisme seperti itu (meskipun saya belum memeriksa).
sumber
Saya akan melemparkan topi saya ke atas ring di sini:
Saya telah menggunakan __call hack dengan tingkat keberhasilan yang beragam. Alternatif yang saya temukan adalah menggunakan pola Pengunjung:
1: menghasilkan stdClass atau kelas kustom (untuk menegakkan tipe)
2: prima dengan metode dan argumen yang diperlukan
3: memastikan bahwa SUT Anda memiliki metode acceptVisitor yang akan menjalankan metode dengan argumen yang ditentukan dalam kelas kunjungan
4: menyuntikkannya ke kelas yang ingin Anda uji
5: SUT menyuntikkan hasil operasi ke pengunjung
6: terapkan kondisi pengujian Anda ke atribut hasil Pengunjung
sumber
Anda memang dapat menggunakan __call () secara umum untuk mengakses metode yang dilindungi. Untuk dapat menguji kelas ini
Anda membuat subkelas di ExampleTest.php:
Perhatikan bahwa metode __call () tidak mereferensikan kelas dengan cara apa pun sehingga Anda dapat menyalin di atas untuk setiap kelas dengan metode yang dilindungi yang ingin Anda uji dan hanya mengubah deklarasi kelas. Anda mungkin dapat menempatkan fungsi ini di kelas dasar umum, tapi saya belum mencobanya.
Sekarang test case itu sendiri hanya berbeda di mana Anda membangun objek yang akan diuji, menukar di ExampleExposed for Example.
Saya percaya PHP 5.3 memungkinkan Anda untuk menggunakan refleksi untuk mengubah aksesibilitas metode secara langsung, tetapi saya berasumsi Anda harus melakukannya untuk setiap metode secara individual.
sumber
call_user_method_array()
fungsi ditinggalkan sebagai PHP 4.1.0 ... menggunakancall_user_func_array(array($this, $method), $args)
sebagai gantinya. Perhatikan bahwa jika Anda menggunakan PHP 5.3.2+ Anda dapat menggunakan Reflection untuk mendapatkan akses ke metode dan atribut yang dilindungi / pribadiAccessible
paket generik yang menggunakan refleksi untuk memungkinkan tes untuk mengakses properti / metode pribadi kelas dan objek.__call()
hanya dipanggil jika pemanggil tidak memiliki akses ke metode. Karena kelas dan subkelasnya memiliki akses ke metode yang dilindungi, panggilan ke mereka tidak akan melalui__call()
. Bisakah Anda memposting kode Anda yang tidak berfungsi di 5.2.7 dalam pertanyaan baru? Saya menggunakan hal di atas dalam 5.2 dan hanya pindah ke menggunakan refleksi dengan 5.3.2.Saya menyarankan solusi berikut untuk solusi / ide "Henrik Paul" :)
Anda tahu nama metode pribadi kelas Anda. Misalnya mereka seperti _add (), _edit (), _delete () dll.
Oleh karena itu ketika Anda ingin mengujinya dari aspek unit-testing, panggil saja metode pribadi dengan awalan dan / atau suffix beberapa kata umum (misalnya _addPhpunit) sehingga ketika __call () metode dipanggil (karena metode _addPhpunit () tidak ada) dari kelas pemilik, Anda cukup memasukkan kode yang diperlukan dalam metode __call () untuk menghapus kata / s yang diawali / suffix (Phpunit) dan kemudian memanggil metode pribadi yang disimpulkan dari sana. Ini adalah penggunaan metode sihir yang bagus.
Cobalah.
sumber