web-dev-qa-db-ja.com

エクスポートされていない関数を単体テストする方法は?

Javascript es6-moduleには、テストする必要があるが、エクスポートしてはならない、小さくてテストしやすい関数が多数ある場合があります。 モジュール内の関数をエクスポートせずにテストするにはどうすればよいですか?rewire を使用せずに)

10
Jordan

「テスト可能な」constをエクスポートする

_function shouldntBeExportedFn(){
  // Does stuff that needs to be tested
  // but is not for use outside of this package
}
export function exportedFn(){
  // A function that should be called
  // from code outside of this package and
  // uses other functions in this package
  return shouldntBeExportedFn();
}
export const testables = {
  shouldntBeExportedFn:shouldntBeExportedFn
}
_

さて

_import {exportedFn} from './myPackage';
_

量産コードで使用でき、

_import {exportedFn, testables} from './myPackage';
const {shouldntBeExportedFn} = testables;
_

単体テストで使用できます。

このようにして、私のチームの他の開発者がshouldntBeExportedFn()をテスト以外のパッケージの外で使用してはならないというコンテキストの手がかりを保持します。

編集:私はこのパターンをほぼ1年間使用しており、非常にうまく機能していることがわかりました。

10
Jordan

ジョーダンにもっと良い答えがあったらいいのに。 ????私は過去にJSとC#の両方のコンテキストで非常に似た質問をしました...

アンサー、答えない

ある時点で、エクスポートされていない/プライベートな関数/メソッドをカバーする詳細な単体テストが必要な場合は、それらを実際に公開する必要があるという事実を受け入れる必要がありました。それはカプセル化の違反だと言う人もいますが、それ以外の人はそれに同意しません。前のグループの人々はまた、関数がエクスポート/公開されるまで、それは本質的に実装の詳細であり、したがってユニットテストされるべきではないと述べます。

TDDを実践している場合は Mark Seemanの説明が適切である必要があります (PluralSight)で、物事を公開しても大丈夫な理由が明確になります。

テスト中のコードに変更を加えずに、ユニットテストから直接、エクスポートされていない関数を呼び出すためのトリックを見つけることができるかどうかはわかりませんが、個人的にはそうしません。

単なるオプション

別のオプションは、ライブラリを2つに分割することです。たとえば、ライブラリAはアプリケーションコードであり、ライブラリBは、Aのインターフェースからのエクスポートを回避するすべての関数を含むパッケージです。

それらが2つの異なるライブラリである場合、公開される内容とテスト方法を非常に細かいレベルで制御できます。ライブラリAは、Bの詳細を漏らすことなく、Bに依存します。次に、ABの両方を個別にテストできます。

確かにこれには別のコード編成が必要ですが、機能します。 Lernaのようなツールは、JavaScriptコードのマルチパッケージリポジトリを簡素化します。

サイドノート

正直なところ、@AlexSzabóに同意しません。エクスポートされていない関数を使用する関数をテストしてテストすることは、実際には単体テストではありません。

4
Igor Soloydenko