web-dev-qa-db-ja.com

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

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

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

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

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

それはテストするのは簡単です:texCompilerpdfMergerは簡単ではないので、関数は実際にはほとんど何もしないので、 モックオブジェクト またはスパイを注入します。私がテストできるのは、両方の関数が正しい順序で呼び出されることだけです。

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

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ファイルをマージしたくないためです。私のモックは適切なイベントを発行して、機能がスタックしないようにする必要があります。

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

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

9
springloaded

どうやらテストのポイントが足りないようです。

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

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

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

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

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

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

8
Telastyn

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

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

2つのPDFファイルをマージし、出力を既知の良好なファイルと比較することにより、あなたのPDFファイルのマージをテストします。

2
Ewan