なぜMockitoは静的メソッドを偽造しないのですか?
私はここで静的メソッドについていくつかのスレッドを読みました、そして私は静的メソッドの誤用/過剰な使用が引き起こす問題を理解していると思います。しかし、静的メソッドをモックするのが難しい理由については、私は実際には理解していませんでした。
私はPowerMockのような他のモックフレームワークがそれを実行できることを知っていますが、なぜMockitoはできないのですか?
私は この記事 と読みましたが、作者はstatic
という言葉に反して宗教的に反対しているようです。
簡単な説明/リンクは素晴らしいでしょう。
その理由は、モックオブジェクトライブラリは通常、実行時に動的にクラスを作成することによってモックを作成するためです( cglib を使用)。これはつまり、実行時にインターフェースを実装すること(これは私が間違っていなければEasyMockが行うことです)、またはクラスからモックすることを継承します(私が間違っていない場合はMockitoが行います)。継承を使用してオーバーライドすることはできないため、どちらの方法も静的メンバーには機能しません。
静的をモックする唯一の方法は、実行時にmodifyクラスのバイトコードにすることです。これは、継承よりも少し複雑です。
それが価値があるもののために、それは私の推測です。
静的メソッドをモックする必要がある場合、それは悪いデザインを表す強い指標です。通常は、テスト対象クラスの依存関係を偽装します。あなたのテスト中のクラスが静的メソッドを参照しているなら - 例えばJava.util.Math#sinのように - それはテスト中のクラスがまさにこの実装を必要とすることを意味します(例えば正確さ対スピード)。もしあなたが具体的なsinusの実装から抽象化したいのなら、おそらくInterfaceが必要です(あなたはこれがどこに向かっているのかわかります)?
静的メソッドもモックする必要があるのなら、私はそれがコード臭であると真剣に思います。
- 一般的な機能にアクセスするための静的メソッド? - >シングルトンインスタンスを使用してそれを注入する
- 第三者コード? - >それをあなた自身のインターフェース/デリゲートにラップしてください(そして必要ならばそれもシングルトンにしてください)
これは私にはやり過ぎだと思う唯一の時ですが、Guavaのようなライブラリですが、とにかくこの種のものをモックする必要はないはずです(ロジックの一部なので...(Iterables.transform(..)などのもの)。
そうすれば、あなた自身のコードをきれいに保つことができ、あなたはすべてのあなたの依存関係をきれいにモックアウトすることができ、そしてあなたは外部の依存関係に対して不正防止層を持つことができます。私はPowerMockを実際に見てきましたが、それを必要とするすべてのクラスは設計が不十分でした。また時々PowerMockの統合は深刻な問題を引き起こしました
(例: https://code.google.com/p/powermock/issues/detail?id=355 )
シモンズ:同じことがプライベートメソッドにも当てはまります。プライベートメソッドの詳細についてテストが知るべきではないと思います。クラスが非常に複雑でプライベートメソッドをモックアウトしたい場合は、おそらくそのクラスを分割することになります。
Mockitoはオブジェクトを返しますが、staticは「オブジェクトレベルではなくクラスレベル」を意味します。したがって、mockitoはstaticに対してnullポインタ例外を発生させます。
場合によっては、静的メソッドをテストするのが難しい場合があります。特に、モックする必要がある場合はそうです。そのため、ほとんどのモックフレームワークはそれらをサポートしていません。 this ブログ記事は、静的メソッドと静的クラスをモックする方法を決定するのに非常に役立つことがわかりました。