TDDモックコール検証-アンチパターンですか?


11

私は1年前からTDDを行っていますが、TDDにはかなり満足しています。テストスイートなど、すべてが大好きです。しかし、最近私は多くの模擬通話検証を行っていることに気づきました。たとえば、リポジトリが挿入されるサービスがあります-単体テストでは、リポジトリのモックを渡し、テストしているメソッド内で呼び出されていることを確認します。次に、返された結果が正しいかどうかを確認します(別のテストで)。私の単体テストは実装の詳細に非常に結びついているので、これは間違いなく間違いだと感じています。「振る舞い」をテストするべきだと聞いたことがありますが、多くの状況では... emm-不可能ですか?あなたが持っている場合voidたとえば、通常は副作用をテストします。つまり、これを実証できる単純なコード型を簡単に示すことができますが、私見では、私たちが作成する実際のプログラムにはあまり反映されていません。私が間違っているのは何ですか?この種のテストは一種のアンチパターンですか?これについてのあなたの意見をいただければ幸いです。TDDに関しては、まだ初心者です。


2
短い答え:はい。このトピックに関する非常に興味深い質問がすでにここのどこかにあります。単体テストは壊れやすく、実装に大きく依存するべきではありません。これが、より高いレベルのテストが必要な理由です(統合など)。ここで:programmers.stackexchange.com/questions/198453/...
Kemoda

@Kemodaディスカッションやこれに関するその他の資料にリンクしていただければ幸いです。私の技術を向上させたいと思っています。
Dimitar Dimitrov 2013

回答:


8

まあ、あなたは入力と出力をテストしようとしているはずです。外部から見える動作を確認する必要があります。クラスが作成する「約束」または「契約」。

同時に、メソッドをテストする方法は、あなたが言ったことを行うよりも優れている場合があります。

私はそれがあなたのテストをよりもろくすると思うので、可能であれば実装の詳細に依存するテストを避けるべきですが、それはすべてか何でもない取り決めではありません。場合によっては問題ありませんが、最悪の場合は、実装を変更してテストを更新する必要があります。


2

テストの目的は、可能な生産的な実装を制限することです。実際に必要な実装のみを制限するようにしてください。通常、これはどのようなあなたのプログラムがすべきではなく、どのようにそれはそれをしません。

たとえば、サービスがリポジトリに何かを追加する場合、後で新しいエントリがリポジトリに含まれていることをテストする必要があります。追加アクションがトリガーされていることをテストする必要はありません。

これを機能させるには、サービスのテストでリポジトリの実装(他の場所でテスト済み)を使用できる必要があります。コラボレーターの実際の実装を使用することは、一般に優れたアプローチであることがわかりました。


「しかし、テストで実際の実装を使用するとコストがかかる場合はどうなりますか(たとえば、設定が複雑なリソースが必要になるため)。この場合、モックを使用する必要がありますよね?」

いずれの場合も、実際の実装が連携して機能することをテストする1つの統合テストがおそらく必要です。この1つの統合テストがサービスのテストに必要なすべてであることを確認してください。または言い換えると、サービスが多数のコラボレーターをプラグインしている(したがって、テストが難しい可能性がある)場合は、ロジックが含まれていないことを確認してください。それが可能で、複数の(統合)テストが必要な場合は、たとえばロジックを分離してよりテストしやすくするなどして、コードの構造を変更する必要があります。

この場合にモックを使用すると、不適切に分離されたロジックの一部をテストする手間が軽減されるため、アーキテクチャ上の問題が隠されます。したがって、モックを使用して不適切に構造化されたコードをテストしないでください。代わりに構造を修正してください。


1
あなたの言っていることがわかります。このトピックは、「どのくらいのテストが多すぎるテスト」であるかについて少し混乱しています。たとえば、基本的にはファサードであり、他のサービス/リポジトリ/コンポーネントの束を単に「接着」している「集約サービス」があるとします。書きますか?私が思いつくことができるのは、電話の確認だけです。私が意味を成していることを願っています。
Dimitar Dimitrov 2013

2

私の考えは、「集約サービス」です。

通話確認はこれを行いますが、あまり価値がありません。配線を確認しているだけです。

これには3つの非排他的な他の方法があります。

  1. より高いレベルの動作を確認できるように、個々のサービスごとのテストを拡張します。たとえば、サービスの単体テストでインメモリデータベースにアクセスする場合は、レベルを上げて、実際のデータベースに対してサービスをテストします。サービス層は抽象化ツリーの上位にあり、テストも同様です。

  2. コード生成を使用して、集約されたサービスから直接サービスを作成します。

  3. 同じことを行うには、何らかのリフレクションまたは動的言語を使用します。たとえば、Javaでは、呼び出しを直接渡すGroovyインターフェースを使用できる場合があります。

これを行う方法はおそらく他にもありますが、配線を確認するだけでは非常に低い利益が得られ、この実装に直接接続することになります。

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