単体テストで、なぜリポジトリを2回作成するのですか?


10

先日、ユニットテストについて少し読んでいて、人々がリポジトリインターフェイス(つまりIExampleRepository)を作成してから、実際のリポジトリ(public class ExampleRepository : IExampleRepository)とユニットテストに使用するリポジトリ()を作成する例をいくつか見ましたFakeExampleRepository : IExampleRepository

IExampleRepositoryそれらはと同じ方法を実施したExampleRepositoryが、異なるLINQクエリと、。

ここの目的は何ですか?コードの単体テストの一部は、メソッドが正しく機能することを確認することだと思いましたか?しかし、「実際の」クエリとテスト内のクエリの2つのまったく異なるクエリを使用すると、テストはどの程度意味がありますか?

回答:


8

単体テストの目的の1つは、一度に1つだけテストすることです。つまり、単一のクラスとメソッドです。リポジトリ自体がテスト中でない場合は、通常、メソッド/クラスのロジックをテストするために、何らかの方法でこれをモックアウトします。

つまり、「実際の」リポジトリ*でもテストする必要がありますが、これは通常、統合/システムテストで行われます。

* テスト用に設定されたリポジトリのように、明らかに本物です。たぶん、たとえば本番DBではありません。


したがって、単体テストでは、メソッド自体をテストして、(偽/偽のデータセットに基づいて)正しい値が返されることを確認しませんか?
jao 2013

はい、メソッド自体をテストしますが、メソッドのコードのみ、他のオブジェクトのコードは他の単体テストでカバーする必要があります。複数のオブジェクトの相互作用は統合テストまたは高レベルのテストでカバーする必要があります
jk。

1
わかりましたので、私が正しく理解していれば、リポジトリを単体テストするときに元のリポジトリを使用する必要があります。コントローラ(Asp.Net MVCの場合)の単体テストを作成しているときに、テストする必要はありません
jao

4
文脈上@Theomax依存します:あなたがある場合はユニットテストでのソフトウェア・コンポーネントではない、あなたがExampleRepository、それはモックを使うのがベストです。正当化するのは、リポジトリを単体テストするのではなく、何か他のものをテストすることです。
アンドレスF.

5
@Theomax AndresF。のコメントを拡張するには:単体テストのExampleRepository場合は、本物を使用してください。単体テストの場合はRepositoryController、事前に指定された値を返すのみを使用する必要がありFakeExampleRepositoryます。このようにバグのゾッとがあればExampleRepository唯一のユニットテストが失敗すること- RepositoryControllerのテストは、あなたはバグが存在しないことを知っているので、成功していきます。コントローラは、実際のリポジトリを使用した場合、彼らは両方とも失敗するだろうとあなたが1つのバグまたは2持っていた場合、あなたは知っているだろう
Izkata

5

私はjkからの2つの答えに同意します。とヤン・ヒューデック-彼らはいくつかの本当に良い情報を提供します。でも少し追加したいと思いました。

最初の質問(「ここでの目的は何ですか?」)は重要です。あなたが説明している場合、本当の目的はIExampleRepository、リポジトリの実装をテストするのではなく、インターフェースを利用しているクラスをテストすることです。を作成するFakeExampleRepositoryと、実際のリポジトリクラスの詳細を気にすることなく、これらのクライアントクラスをテストできます。

これは、設定しようとしているオブジェクトがテストを困難にする場合(たとえば、ファイルシステムへのアクセス、Webサービスの呼び出し、データベースへの通信など)に特に当てはまります。インターフェース(および他のそのような技法)を使用することにより、カップリングを低く保ちます。したがって、クラスXはインターフェースについてのみ知る必要があり、実装の詳細について知る必要はありません。目標は、クラスXが正しいことを行っていることを確認することです。

モッキング(またはスタブ、偽造...微妙な違いがあります)は、単体テストとTDDのための強力なツールです。しかし、これらの実装を手動で作成して維持するのは面倒です。したがって、ほとんどの言語に役立つモックライブラリがあります。C#を使用しているので、シンプルで非常に強力なMoqをお勧めします。その後、モック実装用の追加コードを積み上げることなく、インターフェースに対してテストできます。


the real objective is to test the classes that are utilizing the IExampleRepository interfaceそれは厳密には当てはまりません。目的は、IExampleRepository から独立してテストすることです。ただし、優れた分離フレームワークを推奨する場合は+1。
StuperUser 2013

1
同意しません。IExampleRepositoryテスト対象のクラスがそのインターフェースに結合されているため、これは独立していません。ただし、インターフェースの実装には依存しません。私の説明ではおそらくもう少し洗練されたものを使用できると思います。:)
アラン

5

ここの目的は何ですか?

隔離。

ユニットのアイデアは、可能な限り最小テストするためにそれをテストユニットコードを。これを行うには、テスト内の他のすべての製品コードから分離します。

偽のクラスを作成することで、テスト対象のクラスのみが本番用コードになります。

偽のリポジトリを適切に作成してテストが失敗した場合、問題はテスト対象のコードにあることがわかります。これにより、診断のメリットが無料で得られます。

これらの偽物をすばやく生成してテスト条件を設定し、それらを使用してアサートするための分離フレームワーク(@Allanによって提案されたMoqなど)を見てください。


偽物、モックとスタブの詳細:stackoverflow.com/questions/346372/...
StuperUser

4

単体テストにモックインスタンスを提供する理由は3つあります。

  1. テストの範囲を制限して、テストが宛先のバグの影響を受けないようにします。おそらく、まだ完了していないか、安定していないか、他の誰かのバグがテストに影響を与えたくないためです。
  2. 被扶養者はセットアップが複雑です。たとえば、実際のデータアクセスレイヤーは、実際にテストデータベースをセットアップする必要があるため、モックアウトされることがよくあります。実際のデータアクセスレイヤーをテストする必要がありますが、他のものをデバッグするときにコストのかかるセットアップを制限できます。
  3. 依存クラスがさまざまな種類のエラーに適切に反応することをテストするには、あらゆる種類の間違った答えを返すモックバージョンを提供します。多くの故障モードは再現がかなり困難ですが、それでもテストする必要があります。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.