依存性注入は、テストの負担をさらに連鎖させませんか?


9

私は依存性注入について学んでいます。関数型ライブラリを作成するときにその魅力を見ることができますが、ライブラリを使用する人にもなると、それがどのように解決するのかわかりません。

テストするものがあまりないので、ライブラリのテストがはるかに簡単になります。

しかし、最終的には、ライブラリを使用するときに注入された関数をテストし、標準ライブラリの関数のモックとスタブを処理する必要があります。

これは、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);
}

注入:それはテストに簡単ですモックオブジェクトとして、あるいはスパイをtexCompilerし、pdfMerger機能が本当にすべてではあまり行っていないので、ケーキの一部です。私がテストできるのは、両方の関数が正しい順序で呼び出されることだけです。

とはいえ、最終的には私の関数texCompilerpdfMerger関数をテストする必要はありません。彼らはそのようなものに見えます:

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);
  });
});

これは本物であり、テストすることはより大きな苦痛です。私はモックする必要がchild_process.spawn必ずそれが適切な引数を指定して呼び出さ作るためにスパイで、実際には何もしない、私はテストを実行するときに、実際に任意のPDFファイルをマージしたくないので、私のモックが放出しなければなりませんイベントが正しく機能するので、機能が滞ることはありません。

これらは、最初のスニペットに依存関係を挿入せず、代わりにこれらの関数を使用した場合に発生したであろう問題です。そして、私はそれを解決せずに問題をさらに押し下げているように本当に感じています。

依存性注入を誤解していますか?私はそれを間違っていますか?

回答:


8

どうやらそれをテストするポイントを逃している。

これはテストするのは簡単です。モックやスパイをtexCompilerとpdfMergerに注入するのは簡単です。関数は実際にはまったく何もしないからです。私がテストできるのは、両方の関数が正しい順序で呼び出されることだけです。

驚くばかり!関数がささいな作業をしている場合、テストは簡単なはずです。同様に、その関数が実際に実行しているのがAを呼び出してからBを呼び出す場合は、コードの大部分を検証していません。

優れたテストの全体のポイントは、テストしているものを分離することです。そのため、テストが失敗した場合、何が問題だったかをよりよく知ることができます。依存性注入はそれを助けます。

そして、私はそれを解決せずに問題をさらに押し下げているように本当に感じています。

確かに、この場合は、コードを分離するのが難しい厄介な依存関係があるため、「解決する」ことはできません。ファイルシステムを操作する必要があります。これらの外部プロセスを呼び出す必要があります。時々それは獣の性質です。

Dependency Injectionは依存関係を削除しません。依存関係を反転させるだけで、依存関係を選択できます。これにより、テスト用のコードを分離できます。これらの依存関係が必然的に変更されるときに、コードをより柔軟にするのに役立ちます。しかし、それはそれらを殺すことはありません-あなたのコードはどこかですべて同じことをすることができる必要があります。


それは理にかなっている。これらの厄介な依存関係をテストしやすくするために他にできることはありますか?
15年

2
@springloaded-単なる実用主義。依存関係を分離することは良いことですが、このようなアプリではあまり意味がありません。統合テストは単体テストよりも悪いです(時間がかかり、壊れやすく、原因を特定するのが困難です)が、単体テストで十分な結果が得られない場合は、時間の価値がないかもしれません。
Telastyn、2013年

2

誤解しているのは何かテストだと思います。

PDFファイルを作成し、それを既知の良好なファイルと比較して、PDFファイルの作成をテストします。

2つのPDFファイルをマージし、出力を既知の適切なファイルと比較して、PDFファイルのマージをテストします。


2
それで、あなたは私がこのコードで統合テストをすべきであるがユニットテストをすべきでないと言っていますか?その文脈では、依存性注入は意味がありますか?
15年

3
@springloaded:あなたは有効なポイントを作ります。特定のシナリオではDIが意味をなさないからといって、必ずしもすべてのシナリオで失敗するわけではありません。とにかく、外部ライブラリを扱うことは、主に統合の話です。DIのポイントは、その統合をコードに直接焼き付けるのではなく、その統合をワイヤリング可能にすることです。
Robert Harvey

@RobertHarvey確かに、私はDIが私のユースケースの外でどのように役立つことができるかを見ます
15:10のスプリングロードさ

うーん、そのレベルでの統合テストではありません。必要に応じて、生データを出力し、ディスクへの書き込みを注入して、より「統一性」を高めることができます。
2015年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.