モックオブジェクトを使用するとき、ユニットテストで依存関係の問題をどのように検出しますか?


98

クラスXがあり、動作X1を検証する単体テストを作成します。Xを依存関係とするクラスAもあります。

Aの単体テストを作成するとき、Xをモックします。つまり、Aの単体テスト中に、Xのモックの動作をX1に設定(仮定)します。時間が経ち、人々はあなたのシステムを使用し、変更を必要とし、Xは進化します。Xを変更して動作X2を表示します。明らかに、Xの単体テストは失敗し、それらを調整する必要があります。

しかし、Aではどうでしょうか?Aの単体テストは、Xの動作が変更されても失敗しません(Xのモックにより)。「実際の」(変更された)Xで実行すると、Aの結果が異なることを検出する方法は?

「それは単体テストの目的ではない」という線に沿った答えを期待していますが、単体テストにはどのような価値がありますか?すべてのテストに合格したときに、重大な変更が導入されていないことを本当に伝えているだけですか?そして、あるクラスの振る舞いが(喜んでまたは不本意で)変化するとき、どのようにすべての結果を(できれば自動化された方法で)検出できますか?統合テストにもっと集中すべきではないでしょうか?



36
提案されたすべての答えに加えて、「すべてのテストに合格した場合、重大な変更を導入していないことを本当に伝えているだけですか?」リファクタリングの恐怖を取り除くことがあまり価値がないと思うなら、あなたは維持
不可能な

5
ユニットテストは、コードのユニットが期待どおりに動作するかどうかを示します。多かれ少なかれ。モックとテストダブルは、コード単位を(独立して)実行して、期待どおりかどうかを確認するための、人工的な制御された環境を提供します。多かれ少なかれ。
ロバートハーヴェイ

2
あなたの前提は間違っていると思います。あなたが言及X1するとき、あなたはそれがXインターフェイスを実装していると言っていますX1。他のテストで使用X1X2たモックへのインターフェースを変更すると、もうコンパイルされないはずです。したがって、それらのテストも修正する必要があります。クラスの動作の変更は重要ではありません。実際、クラスAは実装の詳細に依存するべきではありません(これはその場合に変更するものです)。そのため、単体テストAは依然として正しいものでありA、インターフェイスの理想的な実装を前提に動作することがわかります。
バクリウ

5
私はあなたのことは知りませんが、テストなしでコードベースで作業しなければならないとき、私は何かを壊すために死ぬほど怖いです。なぜ?意図しないときに何かが壊れてしまうほど頻繁に起こるからです。そして、テスターの心を祝福してください。彼らはすべてをテストすることはできません。または近い。しかし、ユニットテストは、退屈なルーチンの後、退屈なルーチンを喜んで追い詰めます。
corsiKa

回答:


125

Aの単体テストを記述するとき、Xをモックします。

あなたは?絶対に必要でない限り、私はしません。私がしなければならない:

  1. X 遅い、または
  2. X 副作用があります

これらのどちらも当てはまらない場合、私のユニットAテストXもテストします。他のことをするということは、隔離テストを非論理的な極端なものにすることです。

コードの他の部分のモックを使用してコードの部分がある場合、私は同意します:そのような単体テストのポイントは何ですか?だからこれをしないでください。それらのテストが実際の依存関係を使用するようにしてください。そうすることで、はるかに価値のあるテストが形成されます。

そして、これらのテストを「ユニットテスト」と呼ぶことに怒っている人がいる場合は、単に「自動テスト」と呼び、優れた自動テストの作成に取り掛かります。


94
@Laiv、いいえ、ユニットテストはユニットとして機能する、つまり他のテストから独立して実行されることになっています。ノードとグラフはハイキングすることができます。孤立した、副作用のないエンドツーエンドのテストを短時間で実行できる場合、それは単体テストです。その定義が気に入らない場合は、それを自動テストと呼び、ばかげたセマンティクスに合うようにくだらないテストの作成を停止します。
デビッドアルノ

9
@DavidArno悲しいことに、孤立の非常に広い定義があります。一部の人は、「ユニット」に中間層とデータベースを含めることを望んでいます。彼らは好きなものを信じることができますが、チャンスは、どんなサイズの開発でも、ビルドマネージャーがそれを捨てるので、ホイールがかなり短い順序で外れることです。一般に、それらがアセンブリ(または同等のもの)に分離されている場合、それは問題ありません。注:インターフェイスにコーディングする場合、後でモックとDIを追加する方がはるかに簡単です。
ロビーディー

13
質問に答えるのではなく、異なる種類のテストを提唱しています。これは有効なポイントですが、これはかなり手に負えない方法です。
フィルフロスト

17
@PhilFrost、自分を引用して、「そして、これらのテストを「ユニットテスト」と呼んでいる人々があなたに腹を立てたら、それを単に「自動テスト」と呼び、良い自動テストを書き始めてください。」それは単に単語のランダムな定義を満たしているだけです。または、「ユニットテスト」の定義が間違っている可能性があり、モックが間違っているためにモックを使いすぎていることを受け入れます。いずれにせよ、より良いテストになります。
デビッドアルノ

30
これについては@DavidArnoと一緒です。Ian Cooperによるこの講演を見た後、私のテスト戦略は変わりました:vimeo.com/68375232。それを一文に要約するには:クラスをテストしないでください。テスト動作。テストには、目的の動作を実装するために使用される内部クラス/メソッドに関する知識が必要です。彼らはあなたのAPI /ライブラリの公開面を知っているだけであり、それをテストする必要があります。テストの知識が多すぎる場合、実装の詳細をテストしていることになり、テストは脆弱になり、実装と連動し、実際には首に固定されます。
-Richiban

79

両方が必要です。各ユニットの動作を検証するユニットテスト、およびそれらが正しく接続されていることを確認するためのいくつかの統合テスト。統合テストのみに依存することの問題は、すべてのユニット間の相互作用に起因する組み合わせの爆発です。

クラスAがあり、すべてのパスを完全にカバーするには10個のユニットテストが必要だとします。次に、別のクラスBがあります。このクラスBでは、コードが通過できるすべてのパスをカバーするために10個の単体テストも必要です。アプリケーションで、Aの出力をBにフィードする必要があるとします。これで、コードはAの入力からBの出力までの100の異なるパスを取ることができます。

単体テストでは、すべてのケースを完全にカバーするために、20個の単体テストと1つの統合テストのみが必要です。

統合テストでは、すべてのコードパスをカバーする100のテストが必要になります。

JB Rainsberger Integrated Tests Are A Scam HDのみの統合テストに依存することのマイナス面に関する非常に良いビデオがあります


1
統合テストの有効性に対する疑問符が、すべてのレイヤーをカバーする単体テストと密接に関係しているのは偶然ではないに違いありません。
ロビーディー

16
正しいが、20個のユニットテストでモックが必要な場所はありません。AのすべてをカバーするAの10個のテストと、Bのすべてをカバーする10個のテストがあり、Aの25%をボーナスとして再テストする場合、これは「良い」と良いことの間にあるようです。BsテストでのAのモックは積極的に馬鹿げているようです(Aが問題である理由が実際にない場合、たとえばデータベースであるか、他の物の長いウェブを持ち込む場合)
リチャードティングル

9
完全なカバレッジが必要な場合、単一の統合テストで十分であるという考えに同意しません。Aの出力に対するBの反応は、出力に基づいて異なります。Aのパラメーターを変更すると出力が変更される場合、Bはそれを正しく処理できない可能性があります。
マチューM.

3
@ Eternal21:私のポイントは、時々、問題は個々の行動ではなく、予期しない相互作用にあるということでした。つまり、あるシナリオでAとBの間の接着剤が予期しない動作をする場合です。だから、仕様に応じてAとBの両方の行為、そして幸せなケースでは動作しますが、いくつかの入力に...グルーコードにバグがあります
マシューM.

1
なつみ これは単体テストの範囲を超えていると私は主張します。グルーコードは、単体でテストできますが、グルーコードを介したAとBの相互作用は統合テストです。特定のエッジケースまたはバグが見つかった場合は、それらをグルーコードの単体テストに追加し、最終的に統合テストで検証できます。
アンドリューTフィンネル

72

Aの単体テストを作成するとき、Xをモックします。つまり、Aの単体テスト中に、Xのモックの動作をX1に設定(仮定)します。時間が経ち、人々はあなたのシステムを使用し、変更を必要とし、Xは進化します。Xを変更して動作X2を表示します。明らかに、Xの単体テストは失敗し、それらを調整する必要があります。

ちょっと待って。Xが失敗したことをテストすることの意味はあまりにも重要なので、そのように見直すことはできません。

Xの実装をX1からX2に変更すると、Xの単体テストが壊れる場合、コントラクトXに後方互換性のない変更を加えたことを示します。

X2はでは、Xはないリスコフの感覚あなたがしなければならないので、考えて、あなたの利害関係者のニーズを満たすための他の方法(新しい仕様Yを導入するように、それはX2で実装されている)について。

より深い洞察については、Pieter Hinjens:ソフトウェアバージョンの終わり、またはRich Hickey Simple Made Easyを参照してください。

Aの観点からは、協力者が契約Xを尊重するという前提条件があります。また、事実、Aの分離テストでは、AがX契約に違反する協力者を認識するという保証はありません。

統合テストのレビューは詐欺です。高レベルでは、X2がコントラクトXを正しく実装するために必要な数の隔離されたテストと、Xから興味深い応答が与えられてAが正しいことを行うために必要な数の隔離されたテストが必要です。X2とAがXの意味に同意することを確認するための少数の統合テスト。

この区別は、単独テスト対sociableテストとして表されることがあります。Jay Fields が単体テストで効果的に動作するを参照してください。

統合テストにもっと集中すべきではないでしょうか?

繰り返しますが、統合テストは詐欺です-Rainsbergerは、統合(スペルチェック)テストに依存しているプロジェクトに(経験上)一般的な正のフィードバックループについて詳しく説明しています。要約すると、設計プレッシャーをかける独立した/孤立したテストがないと、品質が低下し、より多くの間違いとより統合されたテストにつながります。

また、(一部の)統合テストも必要になります。複数のモジュールによって導入される複雑さに加えて、これらのテストの実行は、孤立したテストよりも多くの抵抗を伴う傾向があります。作業の進行中に非常に高速なチェックを繰り返し実行する方が効率的であり、「完了」したと思われる場合の追加チェックを保存します。


8
これは受け入れられた答えでなければなりません。この質問は、クラスの動作が互換性のない方法で変更されたが、外見上は同じように見える状況を概説しています。ここでの問題は、単体テストではなく、アプリケーションの設計にあります。この状況をテストで捉える方法は、これら2つのクラス間の統合テストを使用することです。
ニックコード

1
「設計にプレッシャーをかける独立した/孤立したテストがなければ、品質が低下します」。これは重要なポイントだと思います。動作チェックと並んで、単体テストには副作用があり、よりモジュール化された設計を強いられます。
ミカエルグ

これはすべて真実だと思いますが、外部の依存関係が契約Xに後方互換性のない変更を導入した場合、これはどのように役立ちますか?ライブラリのI / O実行クラスが互換性を損なう可能性があります。CIの単体テストが重いI / Oに依存しないようにするため、Xをモックしています。OPはこれをテストするように求めていると思いますが、これがどのように質問に答えているのか理解できません。これをテストする方法は?
ゲリット

15

まず、質問の核となる前提に欠陥があると言ってみましょう。

実装をテスト(またはモック)することはなく、インターフェイスをテスト(およびモック)します

インターフェイスX1を実装する実際のクラスXがある場合、X1にも準拠するモックXMを作成できます。それから、私のクラスAは、クラスXまたはモックXMのいずれかであるX1を実装するものを使用する必要があります。

ここで、Xを変更して新しいインターフェイスX2を実装するとします。まあ、明らかに私のコードはもはやコンパイルされません。AにはX1を実装し、もはや存在しないものが必要です。この問題は特定されており、修正できます。

X1を置き換える代わりに、変更するだけです。これでクラスAがすべて設定されました。ただし、モックXMはインターフェースX1を実装しなくなりました。この問題は特定されており、修正できます。


単体テストとモックの基本は、インターフェイスを使用するコードを書くことです。インターフェイスのコンシューマーは、コードがどのように実装されるかを気にせず、同じコントラクトが(入力/出力)に準拠していることのみを気にします

メソッドに副作用がある場合、これは破綻しますが、「ユニットテストやモックはできません」として安全に除外できると思います。


11
この答えは、保持する必要がない多くの仮定を行います。まず、おおよそ、C#またはJavaを使用していること(より正確には、コンパイルされた言語を使用していること、言語にインターフェースがあり、Xがインターフェースを実装していることを前提としています。これらはいずれも真である必要はありません)。第二に、Xの動作または「契約」への変更には、Xが実装するインターフェース(コンパイラーによって理解される)の変更が必要であると想定しています。JavaやC#を使用している場合でも、これは明らかに真実ではありません。シグネチャを変更せずにメソッドの実装を変更できます。
マークアメリー

6
@MarkAmery「インターフェース」という用語がC#またはJavaに固有であることは確かですが、定義された動作の「契約」を前提としていると思います(コード化されていない場合、これを自動的に検出することは不可能です)。また、契約を変更せずに実装を変更できることも完全に正しいです。ただし、インターフェイス(または契約)を変更せずに実装を変更しても、消費者に影響はありません。Aの動作がインターフェイス(またはコントラクト)の実装方法に依存する場合、(意味的に)ユニットテストを行うことはできません。
Vlad274

1
「また、契約を変更せずに実装を変更できることも完全に正しい」 -事実ですが、これは私が意図したことではありません。むしろ、私はコントラクト(オブジェクトが何をすべきかについてのプログラマーの理解、おそらくドキュメントで指定される)とインターフェース(メソッドシグネチャのリスト、コンパイラーによって理解される)の間の区別を主張し、コントラクトはインターフェイスを変更せずに変更できます。同じシグネチャを持つすべての関数は、型システムの観点から交換可能ですが、実際にはそうではありません!
マークアメリー

4
@MarkAmery:Vladがあなたが使っているのと同じ意味で「インターフェイス」という言葉を使っているとは思わない。私が答えを読んだ方法は、狭いC#/ Javaの意味(つまり、メソッドのシグネチャのセット)でのインターフェースではなく、「アプリケーションプログラミングインターフェース」または「ユーザーインターフェース"。[...]
イルマリカロネン

6
@IlmariKaronen Vladが狭いC#/ Javaの意味ではなく、「インターフェース」を使用して「契約」を意味する場合、「今、Xを変更して新しいインターフェースX2を実装すると仮定します。 」メソッドシグネチャを変更せずにコントラクトを変更できるため、単なるfalseです。しかし、正直なところ、ここでの問題は、Vladがどちらの意味も一貫して使用しておらず、それらを混同していることだと思います。 。
マークアメリー

9

質問を順番に受け取ります:

単体テストにはどのような価値がありますか

書いて実行するのは安価で、早期のフィードバックが得られます。Xを壊すと、適切なテストがあればすぐにわかります。すべてのレイヤーをユニットテストしない限り(データベース上でも)、統合テストの作成を検討しないでください。

すべてのテストに合格したときに、重大な変更が導入されていないことを伝えるだけです。

テストに合格しても、実際にはほとんどわかりません。十分なテストを書いていない可能性があります。十分なシナリオをテストしていない可能性があります。ここではコードカバレッジが役立ちますが、それは特効薬ではありません。常に合格するテストがあるかもしれません。したがって、赤はしばしば見落とされがちな赤、緑、リファクタリングの最初のステップです。

そして、あるクラスの振る舞いが(喜んでまたは不本意で)変化するとき、どのようにすべての結果を(できれば自動化された方法で)検出できますか

より多くのテスト-ツールはどんどん良くなっていますが。ただし、インターフェイスでクラスの動作を定義する必要があります(以下を参照)。注意:テストピラミッドの上部には、手動テストの場所が常にあります。

統合テストにもっと集中すべきではないでしょうか?

さらに多くの統合テストも答えではなく、作成、実行、保守に費用がかかります。ビルドのセットアップに応じて、ビルドマネージャーはそれらを除外し、覚えている開発者に頼るようにします(決して良いことではありません!)。

開発者は、優れた単体テストがあれば5分で発見した壊れた統合テストを修正しようとして何時間も費やしているのを見てきました。これに失敗したら、ソフトウェアを実行してみてください-それはエンドユーザーが気にするすべてです。ユーザーがスイート全体を実行したときにカードの家全体が倒れた場合に合格する百万個のユニットテストがあるという点はありません。

クラスAが同じ方法でクラスXを消費することを確認したい場合は、コンクリートではなくインターフェイスを使用する必要があります。その後、重大な変更がコンパイル時に選択される可能性が高くなります。


9

そのとおりです。

ユニットテストは、ユニットの分離された機能をテストするためにあります。これは、意図したとおりに動作し、愚かなエラーが含まれていないことを一目で確認します。

単体テストは、アプリケーション全体が機能することをテストするためのものではありません。

多くの人が忘れているのは、ユニットテストがコードを検証する最も速くて汚い手段であるということです。小さなルーチンが機能することがわかったら、統合テストも実行する必要があります。単体テストは、テストなしよりもわずかに優れています。

単体テストがある理由は、それらが安価であるはずだからです。作成、実行、および保守が迅速です。それらを最小統合テストに変え始めると、あなたは苦痛の世界に入ります。同様に、完全な統合テストを行って、単体テストをすべて無視することもできます。

現在、一部の人々は、ユニットはクラス内の単なる機能ではなく、クラス全体(自分自身を含む)であると考えています。ただし、これはユニットのサイズを大きくするだけなので、必要な統合テストは少なくなりますが、それでも必要です。完全な統合テストスイートなしでは、プログラムが想定どおりに機能することを検証することはまだ不可能です。

さらに、ライブ(またはセミライブ)システムで完全な統合テストを実行して、顧客が使用する条件で機能することを確認する必要があります。


2

単体テストは、何かの正しさを証明しません。これはすべてのテストに当てはまります。通常、ユニットテストは、契約ベースの設計(契約による設計は別の言い方です)と、正当性を定期的に検証する必要がある場合は自動化された正当性証明と組み合わされます。

クラス不変条件、前提条件、および事後条件で構成される実際の契約がある場合、下位コンポーネントの契約に上位コンポーネントの正当性を基づいて、階層的に正当性を証明することができます。これは、契約による設計の背後にある基本概念です。


単体テストは、何かの正しさを証明しません。私がこれを理解しているかどうかわかりませんが、ユニットテストは自分の結果を確実にチェックしますか?または、複数のレイヤーが含まれる可能性があるため、動作が正しいことを証明できないということですか?
ロビーディー

7
私は推測@RobbieDee、彼はあなたがテストしたときにことを意味しfac(5) == 120、あなたがしているではないことを証明fac()確かにその引数の階乗を返すん。fac()を渡すと、5の階乗を返すことが証明されました5。ようとでもそれは、確かではないfac()考えを返すことができ42トンブクトゥで皆既日食の後の最初の月曜日の代わりに...ここでの問題は、あなたが個々のテスト入力をチェックすることにより、コンプライアンスを証明できないことを、あなたがチェックする必要がありますされ、すべての可能な入力を、また、システムクロックの読み取りなど、忘れていないことを証明します。
cmaster

1
@RobbieDeeテスト(ユニットテストを含む)は、実際の目標であるマシンチェックによる証明の場合、劣った代替手段であり、多くの場合、利用可能な最善のものです。コンポーネントまたはモックの状態空間を含む、テスト対象のユニットの状態空間全体を検討します。非常に制限された状態空間がない限り、テストはその状態空間をカバーできません。完全なカバレッジは証拠になりますが、これは、たとえば、単一の可変バイトまたは16ビット整数を含む単一のオブジェクトをテストするなど、小さな状態空間でのみ使用できます。自動化されたプルーフは非常に価値があります。
フランクヒルマン

1
@cmasterテストと証明の違いを非常によく要約しました。ありがとう!
フランクヒルマン

2

ひどくed笑されたテストはほとんど役に立たないと思います。ほとんどの場合、元のクラスがすでに持っている振る舞いを再実装することになり、モックの目的を完全に無効にします。

私にとってより良い戦略は、懸念事項を適切に分離することです(たとえば、パートBからZを持ち込むことなく、アプリのパートAをテストできます)。このような優れたアーキテクチャは、優れたテストの作成に役立ちます。

また、副作用をロールバックできる限り、喜んで受け入れます。たとえば、私のメソッドがdb内のデータを変更する場合は、許可しましょう。データベースを以前の状態にロールバックできる限り、何が害になりますか?また、データが期待どおりに見えるかどうかをテストで確認できるという利点もあります。インメモリDBまたは特定のdbのテストバージョンは、ここで本当に役立ちます(例:RavenDBsインメモリテストバージョン)。

最後に、サービスの境界でモックをするのが好きです。たとえば、サービスbに対してそのhttp呼び出しを行わないが、インターセプトして適切なものを導入しましょう


1

両方の陣営の人々が、クラステストと行動テストが直交していないことを理解してほしい。

クラステストとユニットテストは同じ意味で使用されますが、使用しないでください。一部の単体テストは、クラスで実装されることがあります。以上です。ユニットテストは、クラスのない言語で何十年もの間行われてきました。

テスト動作については、GWT構造を使用してクラステスト内でこれを行うことは完全に可能です。

さらに、自動化されたテストがクラスに沿って進むか動作に沿って進むかは、むしろ優先度に依存します。あるものは迅速にプロトタイプを作成してドアから取り出す必要があり、あるものはインハウススタイルによるカバレッジの制約があります。多くの理由。どちらも完全に有効なアプローチです。あなたはあなたのお金を支払い、あなたはあなたの選択を取ります。

だから、コードが壊れたときにどうするか。インターフェースにコーディングされている場合、結石だけを変更する必要があります(すべてのテストと一緒に)。

ただし、新しい動作を導入しても、システムを危険にさらす必要はありません。Linuxなどには、非推奨の機能がたくさんあります。そして、コンストラクター(およびメソッド)のようなものは、すべての呼び出しコードを強制的に変更せずに喜んでオーバーロードできます。

クラステストが成功するのは、まだ時間の制約、複雑さなどが原因で、まだ組み込まれていないクラスに変更を加える必要がある場合です。包括的なテストがある場合、クラスを開始するのは非常に簡単です。


あなたがコンクリートを持っているところで、私は実装を書いたでしょう。これは他の言語からの翻訳借用である(私はフランス語を推測する)、または重要な違いがあり結石実装は
ピーターテイラー

0

Xのインターフェースが変更されない限り、Aに関連するものは何も変更されていないため、Aの単体テストを変更する必要はありません。XとAの単体テストを実際に書いたようですが、Aの単体テストと呼んでいるようです。

Aの単体テストを作成するとき、Xをモックします。つまり、Aの単体テスト中に、Xのモックの動作をX1に設定(仮定)します。

理想的には、Xのモックは、Xに期待する動作だけでなく、Xの考えられるすべての動作をシミュレートする必要があります。そのため、インターフェイス自体を変更する以外に、Xを変更しても、Aの単体テストに影響はありません。

例:Aがソートアルゴリズムであり、Aがソートするデータを提供するとします。Xのモックは、null戻り値、空のデータリスト、単一要素、複数の要素が既にソート済み、複数の要素がまだソートされていない、複数の要素が後方にソートされている、同じ要素が繰り返されているリスト、null値が混在している、とんでもない多数の要素があり、例外もスローする必要があります。

したがって、Xは最初に月曜日にソートされたデータを返し、火曜日に空のリストを返しました。しかし、Xが月曜日にソートされていないデータを返し、火曜日に例外をスローする場合、Aは気にしません。これらのシナリオはすでにAの単体テストでカバーされています。


Xが返された配列のインデックスの名前をfoobarからfoobarRandomNumberに変更した場合、どうすればそれをカウントできますか?あなたが私の意見を得るなら、これは基本的に私の問題です。私は返された列の名前をsecondNameから姓に変更しました。これは古典的なタスクです。コメントする前に、この質問の多くの人が実際にそのようなことを試したことがないかのように不思議な感じがします
FantomX1

コンパイラーはこの変更を検出し、コンパイラー・エラーが表示されるはずです。Javascriptのようなものを使用している場合、Typescriptに切り替えるか、このようなものを検出できるBabelのようなコンパイラを使用することをお勧めします。
Mobyディスク

PHP、またはJavaまたはJavascriptで配列を使用している場合、配列のインデックスを変更または削除すると、これらの言語のコンパイラーはそれを教えてくれません。インデックスは36番目にネストされる可能性がありますネストされたレベルの配列。したがって、コンパイラはこれに対する解決策ではないと思います。
FantomX1

-2

さまざまなテストを検討する必要があります。

単体テスト自体はXのみをテストします。Xの動作を変更することはできませんが、システム全体を保護することはできません。動作の変更を導入することなく、クラスをリファクタリングできるようにします。そして、Xを壊すと、それを壊してしまいます...

モックとのユニットテストとテストのためにすべきで実際に模擬Xは、あなたがそれを変更した後も渡しておく必要があります。

しかし、テストには複数のレベルがあります!統合テストもあります。これらのテストは、クラス間の相互作用を検証するためにあります。これらのテストは、すべてにモックを使用しないため、通常は価格が高くなります。たとえば、統合テストは実際にレコードをデータベースに書き込む場合があり、単体テストには外部依存関係がないようにします。

また、Xに新しい動作が必要な場合、望ましい結果を提供する新しいメソッドを提供する方が良いでしょう。

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