Bukankah injeksi ketergantungan mendorong beban pengujian lebih jauh ke bawah rantai?

9

Saya belajar tentang ketergantungan injeksi dan sementara saya bisa melihat daya tariknya ketika menulis pustaka fungsional, saya gagal melihat bagaimana hal itu memecahkan apa pun ketika Anda juga akan menjadi orang yang menggunakan pustaka.

Itu membuat pengujian perpustakaan lebih sederhana, karena tidak banyak yang bisa diuji.

Tetapi pada akhirnya Anda harus menguji fungsi yang disuntikkan ketika Anda menggunakan perpustakaan dan harus berurusan dengan fungsi mengejek dan mematikan dari perpustakaan standar.

Ini adalah kasus nyata yang saya hadapi di Node.js :

function compile(options) {
  var files = options.files;
  var texCompiler = options.texCompiler;
  var pdfMerger = options.pdfMerger;

  return Promise.all(files.map(texCompiler(files)))
    .then(pdfMerger);
}

Itu sepele untuk menguji: menyuntikkan benda-benda tiruan atau mata-mata sebagai texCompilerdan pdfMergersepotong kue karena fungsinya benar-benar tidak berbuat banyak sama sekali. Yang bisa saya uji adalah bahwa kedua fungsi dipanggil dalam urutan yang benar.

Itu tidak menyelamatkan saya dari pengujian texCompilerdan pdfMergerfungsi saya pada akhirnya. Mereka terlihat seperti itu:

var tex2Pdf = Promise.method(function tex2Pdf(tex_doc) {
    var latex_command = 'pdflatex';
    var pdf_output_filename = path.parse(tex_doc).name + '.pdf';
    var cmd = latex_command + ' ' + tex_doc;
    var options = {
      cwd: path.resolve(tex_doc, '..') // pdflatex will only look for custom
      // cls files in the cwd and includes relative to the cwd
    };
    child_process.spawn(cmd, options)
      .on('end', function() {
        console.log('tex2Pdf finish');
        debugger;
        return path.resolve(tex_doc, '..', pdf_output_filename);
      })
      .on('error', function(e) {
        throw e;
      });
});


var mergeTwoPdf = Promise.method(function mergeTwoPdf(pdf_files) {
  var output_file = randomId() + '.pdf';
  var cmd = 'gs -dBATCH -dNOPAUSE -sDEVICE=pdfwrite -sOutputFile=' + output_file + ' ' + pdf_files[0] + ' ' + pdf_file[1];
  child_process.spawn(cmd)
    .on('finish', function() {
      return output_file;
    })
  .on('error', function(e) {
    throw (e);
  });
});

Ini adalah hal yang nyata, dan itu adalah rasa sakit yang lebih besar untuk diuji. Saya harus mengejek child_process.spawndengan mata-mata untuk memastikan itu dipanggil dengan argumen yang benar, tetapi itu tidak benar-benar melakukan apa-apa, karena saya tidak ingin benar-benar menggabungkan file PDF ketika menjalankan tes dan tiruan saya harus memancarkan Peristiwa yang tepat sehingga fungsi tidak macet.

Ini adalah masalah yang akan saya miliki jika saya tidak menyuntikkan dependensi dalam cuplikan pertama saya dan menggunakan fungsi-fungsi ini sebagai gantinya. Dan itu benar-benar terasa seperti saya mendorong masalah lebih jauh tanpa menyelesaikannya.

Apakah saya salah paham injeksi ketergantungan? Apakah saya salah?

springloaded
sumber

Jawaban:

8

Sepertinya Anda melewatkan titik pengujian.

Itu sepele untuk menguji: menyuntikkan ejekan atau mata-mata sebagai texCompiler dan pdfMerger adalah sepotong kue karena fungsinya benar-benar tidak banyak membantu sama sekali. Yang bisa saya uji adalah bahwa kedua fungsi dipanggil dalam urutan yang benar.

Luar biasa! Jika fungsi melakukan pekerjaan sepele, maka tes harus sepele. Demikian juga, jika semua fungsi yang sebenarnya dilakukan adalah memanggil A lalu B, Anda tidak memvalidasi banyak kode Anda.

Inti dari tes yang baik adalah untuk mengisolasi apa yang Anda uji, jadi ketika tes gagal, Anda bisa lebih tahu apa yang salah. Injeksi ketergantungan membantu itu.

Dan itu benar-benar terasa seperti saya mendorong masalah lebih jauh tanpa menyelesaikannya.

Tentu, dalam hal ini Anda tidak "menyelesaikannya" karena kode Anda memiliki dependensi buruk yang sulit untuk diisolasi. Anda perlu bekerja dengan sistem file. Anda perlu memanggil proses eksternal ini. Terkadang itulah sifat binatang itu.

Ketergantungan Injeksi tidak menghapus dependensi, itu hanya membalik sehingga Anda dapat memilih apa itu. Itu membantu mengisolasi kode untuk pengujian. Ini membantu kode menjadi lebih fleksibel ketika dependensi itu mau tidak mau berubah. Tapi itu tidak membunuh mereka - kode Anda masih harus dapat melakukan semua hal yang sama di suatu tempat .

Telastyn
sumber
Itu masuk akal. Apakah ada hal lain yang bisa saya lakukan untuk membuatnya lebih mudah untuk menguji dependensi jahat itu?
springloaded
2
@Springloaded - hanya pragmatisme. Mengisolasi dependensi itu baik, tetapi dalam aplikasi seperti ini, itu tidak masuk akal. Tes integrasi lebih buruk daripada tes unit (butuh waktu lebih lama, lebih rapuh, lebih sulit untuk dikaitkan dengan suatu penyebab) tetapi jika tes unit tidak akan memberi Anda banyak, mereka mungkin tidak sepadan dengan waktunya.
Telastyn
2

Saya pikir ini adalah pengujian yang Anda salah pahami.

Saya akan menguji pembuatan file PDF Anda dengan membuat file PDF dan membandingkannya dengan yang dikenal baik.

Saya akan menguji gabungan file PDF Anda dengan menggabungkan dua file PDF dan membandingkan hasilnya dengan, sekali lagi, file yang bagus.

Ewan
sumber
2
Jadi Anda mengatakan saya harus melakukan tes integrasi pada kode ini tetapi tidak ada tes unit? Dalam konteks itu, apakah injeksi ketergantungan bahkan masuk akal?
springloaded
3
@Springloaded: Anda membuat poin yang valid. Saya hanya akan mengatakan itu, hanya karena DI tidak masuk akal dalam skenario khusus Anda, tidak berarti bahwa itu gagal dalam semua skenario. Berurusan dengan perpustakaan eksternal terutama merupakan cerita integrasi; maksud dari DI adalah membuat integrasi itu dapat ditransfer daripada memanggangnya langsung ke dalam kode Anda.
Robert Harvey
@RobertHarvey Tentu, saya melihat bagaimana DI bisa berguna di luar kasing saya
springloaded
hmm saya katakan ts bukan tes integrasi pada tingkat itu. Jika Anda suka, Anda bisa menampilkan data mentah dan menyuntikkan bit tulis ke cakram jika Anda menginginkannya lebih 'satu'.
Ewan