web-dev-qa-db-ja.com

Java:静的な最終ユーティリティクラスを使用するのではなく、Spring Bean(@Component)を悪用しても大丈夫ですか?

私のコードでDIと静的ユーティリティクラスを使用することに悩んでいます。

現在、静的にアクセスすることのみを目的としたDateUtil静的クラスを作成しています。このクラスは、外部のサードパーティの依存関係がまったくない、さまざまなライブラリを使用して日付を作成および操作するだけです。

すべてが正常に見えますが、静的クラスの動作を適切にスタブ化するためにPowerMockitoを使用する必要があるため、ユニットテストは面倒になります。

逆に、DateUtilの静的性を削除してSpring @Componentに変換した場合、単体テストは少し簡単になりますが、これらすべての依存関係がいたるところにあり、これが確実ではありませんSpringマネージドBeanの目的です。

これをどのように進めればよいですか?どこでもSpring Beanを使用して、静的コードを完全に忘れても大丈夫ですか? SpringのDI機能を悪用しても大丈夫ですか? 「DIが多すぎる」はいつですか?

8
mpmp

静的メソッドは単体テスト可能ではないという一般的な仮定は、インスタンス化可能なクラスインスタンスに対する単体テストの記述に慣れている開発者や、モック、スタブ、インターフェース、依存関係の注入などに付随するすべてのものから生じたようです。静的クラスではこれを行うことはできません。しかしながら ...

Dateのような(多かれ少なかれ)プリミティブ型で動作する静的メソッドは、それを必要としません。静的メソッドが純粋である(つまり、副作用を含まず、静的状態を回避する)と仮定すると、テスト値を指定して呼び出し、正しい戻り結果をアサートするだけでテストできます。

それでおしまい。それ以外のことを行うと、プログラマーは不必要な複雑さの海に沈んでしまい、それ以上のメリットはありません。

非静的クラスには非常に特定の目的があります。その目的が必要な場合は、必ず1つ使用してください。しかし、それが必要ないのであれば、通常のクラステスト手法を適用できないという唯一の理由があるのに、なぜそれを使用するのでしょうか。これを改善するには、テストするコンテナが必要だと思ったからといって、テスト中のメソッドをクラスに分類するのではなく、より適切なテスト手法を学ぶ必要があります。

さらに読む
単体テストでは静的は普遍的に「悪」であり、そうであればなぜResharperはそれを推奨するのですか?

7
Robert Harvey

これが私の経験則です。メソッドが1〜2行しかない場合は静的ユーティリティクラスを使用し、1〜2語で名前を付けるのが簡単で、変更される可能性が非常に低い操作を実行します。したがって、たとえば、Math.max(double, double)は、MoreObjects.firstNonNull(Object...)と同様に、優れた静的ユーティリティメソッドを作成します。

これらのメソッドの動作の定義が変更される可能性は非常に低いため、これらのメソッドを使用する他のクラスをテストするときに、それらの動作を考慮に入れても問題ありません。 Math.max()を使用するメソッドをテストする場合、Math.max()の動作をスタブしないでください。この方法であなたのテストは実際には単体テストではなく、誰が気にするのかと主張することができます。メソッドがStringクラスのメソッドを使用している場合、その動作をスタブしようとしますか?それは意味がありません。

上記の基準が満たされない場合は、通常のDIを使用します。そのため、日付の場合、操作がfirstMondayAfter(Date)のようなものであれば、静的ユーティリティクラスで十分です。 getStartOfMyCompanyFiscalYear(Date)のようなものであれば、DIを使用します。

4