広範囲にモックせずにユニットテストをどのように正確に記述する必要がありますか?


80

私が理解しているように、ユニットテストのポイントは、コードのユニットを単独でテストすることです。この意味は:

  1. コードベースの他の場所にある無関係なコードの変更によって壊れてはなりません。
  2. 統合テスト(ヒープで破損する可能性がある)とは対照的に、テストされたユニットのバグによって破損するユニットテストは1つだけです。

これはすべて、テストされたユニットのすべての外部依存関係をモックアウトする必要があることを意味します。そして、ネットワーク、ファイルシステム、データベースなどの「外部レイヤー」だけでなく、すべての外部依存関係を意味ます。

これは、事実上すべての単体テストがモックする必要があるという論理的な結論につながります。一方、モックに関するGoogleの簡単な検索では、「モッキングはコードのにおい」であると主張する記事が数多くあり、ほとんど(完全にではありませんが)回避する必要があります。

さて、質問へ。

  1. ユニットテストはどのように適切に書かれるべきですか?
  2. それらと統合テストの間の境界線は正確にどこにありますか?

アップデート1

次の擬似コードを検討してください。

class Person {
    constructor(calculator) {}

    calculate(a, b) {
        const sum = this.calculator.add(a, b);

        // do some other stuff with the `sum`
    }
}

依存関係Person.calculateをモックせずにメソッドをテストするテストCalculatorCalculator「外の世界」にアクセスしない軽量クラスであることを考えると)は、単体テストと見なすことができますか?


10
これの一部は、時間とともに来る単なる設計経験です。コンポーネントをモックするのが難しい依存関係が多くないようにコンポーネントを構成する方法を学習します。つまり、テスト容易性は、ソフトウェアの2番目の設計目標でなければなりません。TDDやBDDを使用するなど、コードの前または一緒にテストを記述すると、この目標をはるかに簡単に満たすことができます。
アモン

33
迅速かつ確実に実行されるテストを1つのフォルダーに入れます。低速で脆弱な可能性のあるテストを別のテストに入れます。最初のフォルダーでテストをできるだけ頻繁に実行します(文字列を入力するたびに一時停止し、コードをコンパイルするのが理想的ですが、すべての開発環境がこれをサポートしているわけではありません)。遅いテストの実行頻度を減らします(たとえば、コーヒーブレークがある場合)。ユニット名と統合名について心配する必要はありません。必要に応じて、それらを高速および低速で呼び出します。関係ありません。
デビッドアルノ

6
「事実上、すべてのユニットテストをモックする必要がある」そうですね。「モックに関するGoogleのクイック検索で、「モックはコードの匂いだ」と主張する記事がたくさんあることが明らかになりまし
マイケル

13
@Michael「はい」と言って反対意見を間違っていると宣言するだけでは、このような論争の対象にアプローチするのに最適な方法ではありません。おそらく答えを書いて、なぜあなたはあざけりがどこにでもあるべきだと思うのか、そしておそらく「記事のトン」が本質的に間違っていると思うのかを詳しく説明しますか?
AJFaraday

6
「あざけることはコードの匂いだ」という引用はしていないので、読んだものを誤って解釈していると推測できます。モッキングはコードの匂いではありません。モックを注入するためにリフレクションまたは他のシェナンガンを使用する必要性は、コードのにおいです。モックの難しさは、APIデザインの品質に反比例します。モックをコンストラクターに渡すだけの簡単な単純な単体テストを作成できれば、それは正しいことです。
TKK

回答:


59

単体テストのポイントは、コードのユニットを単独でテストすることです。

単体テストに関するMartin Fowler

ユニットテストはソフトウェア開発でよく話題になりますが、これは私がプログラムを書いている間ずっとよく知っている用語です。しかし、ほとんどのソフトウェア開発用語と同様に、それは非常に不明確であり、実際よりも厳密に定義されていると人々が考えると混乱が生じることがよくあります。

Kent Beckがテスト駆動開発で書いた

私はそれらを「ユニットテスト」と呼んでいますが、受け入れられているユニットテストの定義とはあまり一致していません

「単体テストのポイント」という主張は、「単体テスト」の定義が考慮されているかどうかに大きく依存します。

プログラムが互いに依存する多数の小さなユニットで構成されているという観点で、各ユニットを単独でテストするスタイルに制約する場合、多くのテストダブルが避けられない結論になります。

あなたが見る矛盾するアドバイスは、異なる仮定の下で活動している人々から来ています。

たとえば、リファクタリングのプロセス中に開発者をサポートするテストを作成しており、1つのユニットを2つに分割することをサポートする必要があるリファクタリングである場合、何かを与える必要があります。たぶん、この種のテストには別の名前が必要ですか?または、「ユニット」の異なる理解が必要な場合があります。

あなたは比較したいかもしれません:

計算機の依存関係をモックせずにPerson.calculateメソッドをテストするテスト(計算機は「外の世界」にアクセスしない軽量クラスであると仮定)は、単体テストと見なすことができますか?

それは間違った質問だと思います。私たちが実際に気にしているのはプロパティだと思うとき、それは再びラベルに関する議論です。

コードの変更を導入するとき、テストの分離については気にしません。「ミス」が未検証の編集の現在のスタックのどこかにあることはすでに知っています。テストを頻繁に実行する場合、そのスタックの深さを制限し、間違いを見つけるのは簡単です(極端な場合、テストはすべての編集後に実行されます-スタックの最大深さは1です)。しかし、テストを実行することは目標ではありません-それは中断です-したがって、中断の影響を減らすことには価値があります。中断を減らす1つの方法は、テストが高速であることを確認することです(Gary Bernhardtが300msを提案していますが、私の状況でそれを行う方法がわかりません)。

呼び出しCalculator::addによってテスト(またはこのユースケースの他の重要なプロパティ)の実行に必要な時間が大幅に長くならない場合、テストダブルを使用する必要はありません。コストを上回るメリットはありません。 。

ここでの2つの仮定に注意してください。コスト評価の一部としての人間と、利益評価における未検証の変更の短いスタックです。これらの条件が成立しない状況では、「分離」の値はかなり変化します。

参照してください熱い溶岩をハリー・パーシバルことで、。


5
モックアドが行うことの1つは、電卓モックできること、つまり、デザインが人と電卓を結合しないことを証明することです(ただし、これは他の方法でも確認できます)
jk。

40

広範囲にモックせずにユニットテストをどのように正確に記述する必要がありますか?

コードの副作用を最小限に抑える。

たとえばcalculator、Web APIと通信する場合のサンプルコードを使用すると、そのWeb APIと対話できることに依存する脆弱なテストを作成するか、またはそのモックを作成します。しかし、決定論的で、状態のない計算関数のセットである場合、モックはしません(するべきではありません)。そうすると、モックが実際のコードとは異なる動作をするリスクが生じ、テストのバグにつながります。

モックは、ファイルシステム、データベース、URLエンドポイントなどを読み書きするコードにのみ必要です。実行している環境に依存しています。または、本質的に非常にステートフルで非決定的です。したがって、コードのこれらの部分を最小限に抑え、抽象化の背後に隠すと、モックが簡単になり、コードの残りの部分でモックが不要になります。

副作用のあるコードポイントについては、模擬テストとそうでないテストを書く価値があります。ただし、後者は本質的に脆弱であり、おそらく遅いため、注意が必要です。そのため、コードを保存してビルドするたびにではなく、CIサーバーで一晩だけ実行することをお勧めします。ただし、前者のテストは実行可能な限り頻繁に実行する必要があります。各テストが単体テストであるか統合テストであるかについては、アカデミックになり、ユニットテストであるかどうかに関する「炎の戦争」を回避します。


8
これは、実際上および意味のない意味論的議論を回避するという点で正しい答えです。
ジャレッド・スミス

そのようなスタイルを使用し、それでも良好なテストカバレッジが得られる、重要なオープンソースコードベースの例はありますか?
ジョーリセブレヒト

4
@JoeriSebrechts FP 1つすべてですか?
Jared Smith、

私が探しているものとはまったく異なります。それは、互いに独立した関数のコレクションであり、相互に呼び出す関数のシステムではないからです。関数が最上位の関数の1つである場合、テストするために関数の複雑な引数を作成する必要はありませんか?たとえば、ゲームのコアループ。
ジョーリセブレヒト

1
@JoeriSebrechtsうーん、私はあなたが望むものを誤解しているか、あなたが私が与えた例に深く掘り下げていませんでした。ramda関数は、ソース内のあらゆる場所で内部呼び出しを使用します(例:)R.equals。これらはほとんど純粋な関数であるため、一般的にテストではモックされていません。
ジャレッド・スミス

31

これらの質問の難易度はかなり異なります。最初に質問2を見てみましょう。

単体テストと統合テストは明確に分離されています。単体テストでは、1つのユニット(メソッドまたはクラス)をテストし、その目標を達成するために必要なだけ他のユニットを使用します。モッキングが必要な場合がありますが、テストのポイントではありません。統合テストは、異なる実際のユニット間の相互作用をテストします。この違いが、ユニットテストと統合テストの両方を必要とする理由の全体です。一方が他方の仕事を十分に行ったとしても、そうではありませんが、1つの汎用ツールよりも2つの専用ツールを使用する方が通常は効率的であることが判明しました。

ここで重要な質問です。ユニットテストはどのように行うべきですか?上記のように、単体テストでは必要な範囲でのみ補助構造を構築する必要があります。多くの場合、あなたの本当のデータベース、さらにはよりモックデータベースを使用する方が簡単である任意の実際のデータベース。ただし、モック自体には価値はありません。頻繁に発生する場合、実際には中間レベルの単体テストの入力として別のレイヤーの実際のコンポーネントを使用する方が簡単です。もしそうなら、それらを使用することをheしないでください。

多くの開業医は、ユニットテストBがユニットテストAで既にテストされたクラスを再利用する場合、ユニットAの欠陥が複数の場所でテストの失敗を引き起こすことを恐れています。テストスイートが成功しなければならない:私はこれではない問題を検討し、100%を -結局、あなたはそれがあまりにも多くの障害を持っている大きな問題ではありませんので、あなたが必要安心感を与えるために行う欠陥を持っています。欠陥があまりにトリガーた場合のみ、重大な問題は次のようになり、いくつかの障害を。

したがって、m笑の宗教を作らないでください。これは手段であり、目的ではありません。したがって、余分な労力を避けて逃げることができるのであれば、そうするべきです。


4
The only critical problem would be if a defect triggered too few failures.これは、モックの弱点の1つです。予想される動作を「プログラミング」する必要があるため、失敗するとテストが「誤検知」として終了する可能性があります。しかし、モックは決定論(テストの最も重要な条件)を達成するために非常に便利な手法です。可能な場合は、すべてのプロジェクトでそれらを使用します。また、統合が複雑すぎる場合や依存関係が厳しすぎる場合にも表示されます。
ライヴ

1
テストされているユニットが他のユニットを使用している場合、それは本当に統合テストではありませんか?本質的に、このユニットは、統合テストとまったく同じように、上記ユニット間の相互作用をテストするからです。
アレクサンダーロミア

11
@AlexanderLomia:ユニットとは何ですか?「String」もユニットと呼びますか?私はそうしますが、私はそれをあざけることを夢見ません。
バートヴァンインゲンシェ

5
単体テストと統合テストは明確に分離されています。単体テストは、1つのユニット(メソッドまたはクラス)をテストし、その目標を達成するために必要なだけ他のユニットを使用します。」ここにこすります。それがありますあなたのユニットテストの定義。私のものはまったく違います。そのため、それらの区別は特定の定義に対して「明確に分離されている」だけですが、分離は定義によって異なります。
デビッドアルノ

4
@Vooこのようなコードベースで作業したが、元の問題を見つけるのは面倒かもしれませんが(特に、デバッグするために使用するものをアーキテクチャが塗りつぶした場合)、モックの問題がさらに発生しました。テストに使用したコードが壊れた後も動作し続けるテスト。
-James_pic

6

では、質問に直接答えるには:

ユニットテストはどのように適切に書かれるべきですか?

あなたが言うように、依存関係をあざけり、問題のユニットだけをテストする必要があります。

それらと統合テストの境界はどこにありますか?

統合テストは、依存関係がモックされていない単体テストです。

計算機をモックせずにPerson.calculateメソッドをテストするテストを単体テストと見なすことはできますか?

いいえ。計算機の依存関係をこのコードに挿入する必要があり、モックバージョンと実際のバージョンのどちらかを選択できます。模擬テストを使用する場合は単体テスト、実際のテストを使用する場合は統合テストです。

ただし、注意が必要です。あなたはテストが呼ばれるべきだと人々が考えるものを本当に気にしますか?

しかし、あなたの本当の質問はこれのようです:

モックに関する簡単なGoogle検索では、「モックはコードのにおい」であると主張し、ほとんど(完全にではありませんが)回避すべきであると主張する多数の記事が明らかになります。

ここでの問題は、多くの人がモックを使用して依存関係を完全に再作成することだと思います。たとえば、私はあなたの例で電卓をモックするかもしれません

public class MockCalc : ICalculator
{
     public Add(int a, int b) { return 4; }
}

私は次のようなことはしません:

myMock = Mock<ICalculator>().Add((a,b) => {return a + b;})
myPerson.Calculate()
Assert.WasCalled(myMock.Add());

私は、それは「私のモックをテストする」または「実装をテストする」と主張します。「モックを書かないで! *そのように」と言うでしょう。

他の人は私に反対します、私たちはブログでモックへの最良の方法について大規模なフレーム戦争を開始します。良いテストを書きたいだけの人に。


徹底的な回答をありがとう。他の人が私のテストについてどう考えているかを気にかけるように-実際、プロジェクトが進行するにつれて信頼性の低い混乱になりがちな半統合、半ユニットテストを書くのを避けたいと思っています。
アレクサンダーロミア

問題はありません。問題は、2つのことの定義が全員によって完全に合意されていないことだと思います。
ユアン

私はあなたのクラスの名前を変更するだろうMockCalcStubCalc、とスタブないモックそれを呼び出します。martinfowler.com/articles/...
BDSL

@bdslその記事は15歳です
ユアン

4
  1. ユニットテストはどのように適切に実装されるべきですか?

私の経験則では、適切な単体テストは次のとおりです。

  • 実装ではなく、インターフェイスに対してコーディングされます。これには多くの利点があります。一つは、それはあなたのクラスが従うことを保証します依存関係逆転の原則をからSOLID。また、これは他のクラスが行うことです(右?)ので、テストも同じようにする必要があります。また、これにより、テストコードの大部分を再利用しながら、同じインターフェイスの複数の実装をテストできます(初期化と一部のアサーションのみが変更されます)。
  • 自己完結型です。あなたが言ったように、外部コードの変更はテスト結果に影響を与えることはできません。そのため、単体テストはビルド時に実行できます。つまり、副作用を取り除くにはモックが必要です。ただし、Dependency Inversion Principleに従う場合、これは比較的簡単です。Spockのような優れたテストフレームワークを使用すると、最小限のコーディングでテストで使用する任意のインターフェイスのモック実装を動的に提供できます。つまり、各テストクラスは、1つの実装クラスとテストフレームワーク(およびモデルクラス["beans"])からコードを実行するだけで済みます。
  • 別の実行中のアプリケーションは必要ありません。テストが「何かと話す」必要がある場合、データベースであろうとWebサービスであろうと、それは単体テストではなく統合テストです。ネットワーク接続またはファイルシステムに線を引きます。たとえば、純粋にインメモリのSQLiteデータベースは、本当に必要な場合の単体テストとしては公平なゲームです。

ユニットテストを複雑にするフレームワークのユーティリティクラスがある場合、非常に単純な「ラッパー」インターフェースとクラスを作成して、それらの依存関係のモックを作成すると便利です。これらのラッパーは必ずしも単体テストの対象とはなりません。

  1. それら[ユニットテスト]と統合テストの間の境界線はどこに正確にありますか?

この区別が最も有用であることがわかりました。

  • ユニットテストは、「ユーザーコード」をシミュレートしコードレベルインターフェイスの望ましい動作とセマンティクスに対する実装クラスの動作を検証します
  • 統合テストはユーザーをシミュレートし、指定されたユースケースや正式なAPIに対する実行中のアプリケーションの動作を検証します。Webサービスの場合、「ユーザー」はクライアントアプリケーションになります。

ここに灰色の領域があります。たとえば、Dockerコンテナでアプリケーションを実行し、ビルドの最終段階として統合テストを実行し、その後コンテナを破棄できる場合、それらのテストを「単体テスト」として含めることはできますか?これがあなたの燃える議論であるなら、あなたはかなり良い場所にいます。

  1. 事実上すべての単体テストがモックする必要があるのは本当ですか?

いいえ。個々のテストケースの中にはnull、パラメータとして渡したり、例外が発生したことを確認したりするなど、エラー条件用のものがあります。そのようなテストの多くは、モックを必要としません。また、文字列処理や数学関数などの副作用のない実装では、出力を確認するだけなので、モックは必要ありません。しかし、持つ価値のあるほとんどのクラスには、テストコードのどこかに少なくとも1つのモックが必要になると思います。(少ないほど良い。)

あなたが言及した「コードのにおい」の問題は、テストを書くためにモックの依存関係の長いリストを必要とする、非常に複雑なクラスがあるときに発生します。これは、各クラスのフットプリントが小さく、責任が明確になるように実装をリファクタリングして分割する必要がある手がかりであり、テストが容易になります。これにより、長期的に品質が向上します。

1つのユニットテストのみが、テストされたユニットのバグによって中断します。

再利用に対して機能するため、これは合理的な期待とは思わない。privateたとえば、publicインターフェイスによって公開された複数のメソッドによって呼び出されるメソッドがある場合があります。その1つのメソッドに導入されたバグは、複数のテストの失敗を引き起こす可能性があります。これは、同じpublicメソッドを各メソッドにコピーする必要があるという意味ではありません。


3
  1. コードベースの他の場所にある無関係なコードの変更によって壊れてはなりません。

私はこのルールがどのように役立つか本当に分かりません。あるクラス/メソッド/何かの変更が実動コード内の別のクラス/メソッドの振る舞いを壊す可能性がある場合、それらは実際には共同作業者であり、無関係ではありません。テストが中断し、運用コードが中断しない場合、テストは疑わしいものです。

  1. 統合テスト(ヒープで破損する可能性がある)とは対照的に、テストされたユニットのバグによって破損するユニットテストは1つだけです。

私もこのルールを疑っていると思います。コードを構造化し、1つのバグが1つの単体テストの失敗を引き起こすようにテストを記述するのに本当に十分であれば、コードベースが使用するケースに進化しているとしても、潜在的なすべてのバグをすでに特定していると言います予期していませんでした。

それらと統合テストの境界はどこにありますか?

それは重要な違いだとは思いません。とにかくコードの「ユニット」とは何ですか?

そのレベルのコードが扱っている問題のドメイン/ビジネスルールの観点から「意味をなす」テストを作成できるエントリポイントを見つけてください。多くの場合、これらのテストは本質的にやや「機能的」です。入力を行い、出力が期待どおりであることをテストします。テストがシステムの望ましい動作を表現する場合、実稼働コードが進化してリファクタリングされた場合でも、テストはしばしば非常に安定したままです。

広範囲にモックせずにユニットテストをどのように正確に記述する必要がありますか?

「ユニット」という言葉を読みすぎず、テストで実際のプロダクションクラスを使用することに傾倒しないでください。テストに複数のクラスを含める場合は、あまり心配する必要はありません。それらのいずれかが使いにくい場合(多くの初期化が必要なため、または実際のデータベース/メールサーバーにアクセスする必要があるため)、考えをモック/偽装に変えてください。


とにかくコードの「ユニットとは何ですか?」誰が答えているかに依存するかもしれない予想外の答えを持つことができる非常に良い質問。通常、単体テストのほとんどの定義では、それらをメソッドまたはクラスに関連するものとして説明していますが、それはすべての場合において「ユニット」の実際に有用な尺度ではありません。私が持っている場合Person:tellStory()メソッドは文字列の中に、人の詳細を取り入れ、その後、その後、「物語」は、おそらく1個の単位であることを返します。コードの一部を取得するプライベートヘルパーメソッドを作成する場合、新しいユニットを導入したとは思わない-個別にテストする必要はありません。
VLAZ

1

まず、いくつかの定義:

単体テストでは、ユニットを他のユニットから分離してテストしますが、その意味は信頼できるソースによって具体的に定義されていないため、もう少し適切に定義してみましょう:I / O境界を越える場合(I / Oがネットワーク、ディスク、画面、またはUI入力)、線を引くことができる半客観的な場所があります。コードがI / Oに依存している場合、ユニットの境界を越えているため、そのI / Oを担当するユニットをモックする必要があります。

その定義の下では、純粋な関数のようなものをモックする説得力のある理由は見当たりません。つまり、単体テストは純粋な関数、または副作用のない関数に向いているということです。

効果のあるユニットを単体テストする場合、効果の原因となるユニットをモックする必要がありますが、代わりに統合テストを検討する必要があります。したがって、簡単な答えは、「モックが必要な場合、本当に必要なのは統合テストかどうかを自問することです」しかし、より良い、より長い答えがここにあり、ウサギの穴はずっと深くなります。モックは、学ぶべきことがたくさんあるので、私のお気に入りのコードの匂いかもしれません。

コードの匂い

このために、ウィキペディアに目を向けます。

コンピュータープログラミングでは、コードの匂いは、より深い問題を示す可能性のあるプログラムのソースコードの特性です。

後で続きます...

「臭いは、基本的な設計原則の違反を示し、設計品質に悪影響を及ぼすコード内の特定の構造です」。ギリッシュのスリヤナラヤナ(2014年11月)。ソフトウェア設計の匂いのリファクタリング。モーガン・カウフマン。p。258。

コードのにおいは通常バグではありません。それらは技術的に正しくなく、プログラムの機能を妨げません。代わりに、開発の速度を落としたり、将来のバグや障害のリスクを高める可能性のある設計上の弱点を示しています。

言い換えれば、すべてのコードの匂いが悪いわけではありません。代わりに、それらは何かが最適な形で表現されないかもしれないという一般的な兆候であり、匂い問題のコードを改善する機会を示すかもしれません。

モックの場合、臭いは、モックを要求していると思われるユニットがモックされるユニットに依存していることを示します。問題を原子的に解決可能な部分に分解しておらず、ソフトウェアの設計上の欠陥を示している可能性があります。

すべてのソフトウェア開発の本質は、大きな問題をより小さな独立した部分に分解し(分解)、ソリューションを一緒に構成して大きな問題を解決するアプリケーション(構成)を作成するプロセスです。

大きな問題を小さな部品に分解するために使用されるユニットが互いに依存している場合、モッキングが必要です。別の言い方をすれば、想定される構成の原子単位が実際には原子ではなく、分解戦略がより大きな問題をより小さな独立した解決すべき問題に分解できなかった場合に、モッキングが必要です。

コードの匂いをモックにするのは、モックに本質的に問題があるということではありません-時には非常に便利です。それをコードの匂いにしているのは、アプリケーションのカップリングの問題のあるソースを示している可能性があることです。時々、そのカップリングのソースを削除することは、モックを書くよりもはるかに生産的です。

カップリングには多くの種類があり、一部は他よりも優れています。モックがコードの匂いであるということを理解することで、匂いがさらに悪化するに、アプリケーション設計ライフサイクルの初期段階で最悪の種類を特定して回避することができます。


0

モックは、単体テストであっても最後の手段としてのみ使用してください。

メソッドはユニットではなく、クラスでさえユニットではありません。ユニットとは、コードを論理的に分離したもので、何を呼んでも意味があります。十分にテストされたコードを持つ重要な要素は、自由にリファクタリングできることであり、自由にリファクタリングできることの一部は、そうするためにテストを変更する必要がないことを意味します。モックするほど、リファクタリング時にテストを変更する必要があります。メソッドをユニットと見なす場合、リファクタリングするたびにテストを変更する必要があります。クラスをユニットと見なす場合、クラスを複数のクラスに分割するたびにテストを変更する必要があります。コードをリファクタリングするためにテストをリファクタリングする必要がある場合、人々はコードをリファクタリングしないことを選択します。これは、プロジェクトで起こりうる最悪の事態です。テストをリファクタリングせずにクラスを複数のクラスに分割できるか、または500行を超えるサイズのスパゲッティクラスになることが不可欠です。ユニットテストでメソッドまたはクラスをユニットとして扱う場合は、おそらくオブジェクト指向プログラミングではなく、オブジェクトを使用した何らかのミュータント関数プログラミングを行っていることになります。

単体テスト用にコードを分離しても、それ以外のすべてをモックするわけではありません。もしそうなら、あなたはあなたの言語の数学クラスをモックする必要があり、絶対に誰もそれが良い考えだとは思わないでしょう。内部の依存関係は、外部の依存関係とは異なる方法で処理されるべきではありません。あなたはそれらが十分にテストされており、彼らが想定されているように動作することを信頼しています。唯一の本当の違いは、内部の依存関係がモジュールを壊している場合、GitHubに問題を投稿して修正するために理解していないコードベースを掘り下げることなく、修正するためにやっていることを停止できることですまたは最高を願っています。

コードを分離するということは、内部依存関係をブラックボックスのように扱い、内部で発生していることをテストしないことを意味します。1、2、または3の入力を受け入れるモジュールBがあり、それを呼び出すモジュールAがある場合、モジュールAのテストでこれらの各オプションを実行するのではなく、1つを選択して使用します。つまり、モジュールAのテストでは、モジュールBからの応答を処理するさまざまな方法をテストする必要があります。モジュールBに渡すものではありません。

したがって、コントローラーが複雑なオブジェクトを依存関係に渡し、その依存関係がデータベースに保存してさまざまなエラーを返す可能性がある場合、そのコントローラーが実際に行うのは、それが返すかどうかを確認することだけですエラーかどうかとその情報を渡すと、コントローラーでテストするのは、エラーが返されてエラーが返されたかどうかのテストと、エラーが返されないかどうかのテストだけです。データベースに何かが保存されたかどうか、またはエラーがどのようなエラーであるかをテストしません。それは統合テストになるからです。これを行うために、依存関係をモックする必要はありません。コードを分離しました。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.