Apakah membungkus kode pihak ketiga satu-satunya solusi untuk menguji unit konsumennya?

13

Saya sedang melakukan pengujian unit dan di salah satu kelas saya, saya perlu mengirim email dari salah satu metode, jadi menggunakan injeksi konstruktor saya menyuntikkan contoh Zend_Mailkelas yang ada di kerangka Zend.

Sekarang beberapa orang berpendapat bahwa jika perpustakaan cukup stabil dan tidak akan sering berubah maka tidak perlu membungkusnya. Jadi dengan asumsi itu Zend_Mailstabil dan tidak akan berubah dan itu sesuai dengan kebutuhan saya sepenuhnya, maka saya tidak akan memerlukan pembungkus untuk itu.

Sekarang lihat kelas saya Loggeryang tergantung pada Zend_Mail:

class Logger{
    private $mailer;    
    function __construct(Zend_Mail $mail){
        $this->mail=$mail;
    }    
   function toBeTestedFunction(){
      //Some code
      $this->mail->setTo('some value');
      $this->mail->setSubject('some value');
      $this->mail->setBody('some value');
      $this->mail->send();
     //Some
   }        
}

Namun, pengujian Unit menuntut saya menguji satu komponen pada satu waktu, jadi saya perlu mengejek Zend_Mailkelas. Selain itu saya melanggar prinsip Ketergantungan Pembalikan karena Loggerkelas saya sekarang tergantung pada konkret bukan abstraksi.

Sekarang bagaimana saya bisa menguji Loggerdalam isolasi tanpa pembungkus Zend_Mail?!

Kode ini dalam PHP, tetapi jawabannya tidak harus. Ini lebih merupakan masalah desain daripada fitur khusus bahasa

Songo
sumber
Apakah Anda harus menggunakan antarmuka? Apakah PHP tidak mendukung mengetik bebek?
kevin cline
@ kevincline saya menggunakan PHP karena bahasa yang paling saya gunakan, tapi saya sebenarnya mencari solusi umum untuk masalah tidak terbatas pada PHP saja.
Songo

Jawaban:

21

Anda selalu ingin membungkus tipe dan metode pihak ketiga di belakang sebuah antarmuka. Ini bisa membosankan dan menyakitkan. Terkadang Anda dapat menulis generator kode atau menggunakan alat untuk melakukan ini.

Tetapi jangan tergoda untuk menggunakan metode atau tipe pustaka di seluruh kode Anda. Untuk memulainya, Anda akan kesulitan menulis unit test. Kemudian lisensi akan berubah, atau Anda ingin pergi ke platform yang tidak didukung oleh pihak ketiga, dan Anda akan menemukan bahwa tipe dan dependensi tersebut telah terjalin di dalam dan di sekitar semua kelas Anda yang lain.

Kemampuan untuk mengubah vendor pihak ketiga dengan cepat adalah keuntungan besar.

Ben
sumber
4
"Apa pun yang tidak ditulis oleh Anda" agak banyak. Perpustakaan yang merupakan bagian dari standar atau platform sulit untuk dibungkus. Anda mungkin tidak ingin membungkus semua komponen .NET, misalnya. Jika pembungkus hanya melewati antarmuka, atau dihasilkan kode, saya telah menemukan sedikit manfaat untuk menulis tes. Jika ada logika di sana (menggabungkan panggilan, dll.) Tes dapat membantu.
Ben
3
Terpilih untuk kalimat terakhir.
Blrfl
1
Jika Anda melakukan refactor dengan benar, setiap penggunaan berulang fasilitas perpustakaan akan diperhitungkan sebagai kelas layanan. Tidak perlu mendefinisikannya di muka.
kevin cline
3
-1: Kecuali dalam kasus di mana perpustakaan pihak ketiga menyediakan layanan yang memiliki API terstandarisasi, ini adalah pemborosan waktu yang sangat besar dan hanya akan mengurangi perawatan dengan meminta Anda membuat duplikat kode. Juga, YAGNI.
Michael Borgwardt
1
@MichaelBorgwardt: Tentu, tetapi dalam hal itu, API standar menjadi pembungkus dan Anda dapat bertukar perpustakaan dengan mudah.
Blrfl