Mockitoが静的メソッドをモックしないのはなぜですか?


267

静的メソッドについてここでいくつかのスレッドを読み、静的メソッドの誤用/過度の使用が引き起こす可能性がある問題を理解していると思います。しかし、静的メソッドをモックするのが難しい理由の根本には至りませんでした。

PowerMockなどの他のモックフレームワークがそれを実行できることを知っていますが、なぜMockitoができないのですか?

私はこの記事を読みましたが、作者は宗教的にこの言葉staticに反対しているようです。おそらく私の理解不足です。

簡単な説明/リンクがいいでしょう。


12
余談ですが、PowerMock自体はモックオブジェクトライブラリではなく、他のライブラリの上にこれらの機能(静的およびctorのモック)を追加するだけです。私たちは、PowerMock + Mockitoを使用して、お互いによく浮かんでいます。
Matthias

回答:


238

モックオブジェクトライブラリは通常、実行時にクラスを動的に作成することにより(cglibを使用して)モックを作成するためと思われます。これは、実行時にインターフェースを実装するか(私が誤っていない場合はEasyMockが行うこと)、またはクラスから継承してモックする(誤っていない場合はMockitoが行うこと)のいずれかです。継承を使用してそれらをオーバーライドすることはできないため、どちらの方法も静的メンバーに対しては機能しません。

静的をモックする唯一の方法は、実行時にクラスのバイトコードを変更することです。これは継承よりも少し複雑だと思います。

それは価値があるので、それは私の推測です...


7
ちなみに、コンストラクターのモックも同じです。これらも継承によって変更することはできません。
Matthias

11
一部のTDD / TBD支持者は、静的メソッドとコンストラクターのモックの欠如を良いものとして認識していることも付け加える価値があるかもしれません。静的メソッドまたはコンストラクターをモックする必要があると感じた場合、これはクラス設計が不十分であることの指標であると彼らは主張します。たとえば、コードモジュールのアセンブルにおいて純粋なIoCアプローチに従う場合、静的またはctorをそもそもモックする必要はありません(もちろん、ブラックボックスコンポーネントの一部でない限り)。参照してくださいgiorgiosironi.blogspot.com/2009/11/...
マティアス・

200
私は、モックツールがあなたにとって何がより良いかを知っていると仮定せずに、あなたがあなたに必要なものを与えるべきだと思います。たとえば、モックするために必要な静的メソッド呼び出しを利用するサードパーティのライブラリを使用している場合、そうすることができればすばらしいでしょう。モックフレームワークは設計が悪いと見なされているため、一部の機能を提供しないという考えには根本的な欠陥があります。
Lo-Tan

11
@ Lo-Tan-それは、言語があなたよりもよく知っていると仮定するのではなく、言語がすべての能力を持つべきだと言っているようなものです。それらは印象的なものとして脱落するので、それはあなたの側の単なる虚栄心です。ここでの問題は、「対静的/静的」バトルが明確ではなく、フレームワークも同様であるということです。私たちは両方を持つべきだと思います。しかし、事実明確である場合、私それらの事実を課すフレームワークを好みます。それは学習の1つの方法です。だからあなた自身はする必要はありません。しかし今、すべての麺の頭は、いわゆる「良いデザイン」を課すことができます。「根本的に欠陥がある」...
nevvermind 2014年

13
@nevvermindえ?高水準言語は、重要な部分に集中できるように、必要な抽象化を支援することを目的としています。テストライブラリはツールです。これは、より良い品質のコードを作成するために使用するツールです。他の誰かの設計が不十分なコードを統合しなければならないときに使用できないことを意味する制限があるテスト/モックライブラリのポイントは何ですか?よく考えられていないようですが、良い言語はそうです。
Lo-Tan

28

静的メソッドを模擬する必要がある場合、それは悪いデザインの強力な指標です。通常、テスト対象のクラスの依存関係を模倣します。テスト対象のクラスが静的メソッド(たとえば、java.util.Math#sinなど)を参照している場合は、テスト対象のクラスが正確にこの実装を必要としていることを意味します(たとえば、精度対速度)。具体的な正弦の実装から抽象化したい場合は、おそらくインターフェイスが必要です(これがどこに行くのかわかりますか)?


3
まあ、私は静的メソッドを使用して、「静的永続性ファサード」などの高レベルの抽象化を提供しました。このようなファサードにより、ORM APIの複雑さと低レベルの詳細からクライアントコードを遠ざけ、より一貫性があり使いやすいAPIを提供すると同時に、多くの柔軟性を実現します。
ホジェリオ

そして、なぜそれをあざける必要があるのですか?静的メソッドに依存している場合、「ユニット」または「モジュール」はクラスだけではなく、「静的永続性ファサード」も含みます。
1

88
真ですが、たとえば、サードパーティのクラスにある静的メソッドをモックする必要がある場合は、選択の余地がない場合があります。
Stijn Geukens

6
本当ですが、シングルトンを扱うこともあります。
Manu Manjunath、2015年

抽象化によって解決できない唯一の考えは、抽象化のレベルが多すぎることです...抽象化レイヤーを追加すると、複雑さが増し、多くの場合不要になります。私は、この単純な呼び出しを単一のクラスにラップすることによってSystem.currentTimeMillis()をモックしようとするフレームワークの例を見たと思います。テストを容易にするためだけに、単純にメソッドを持つのではなく、メソッドごとにシングルトンクラスを作成します。そして、シングルトンラッパーの代わりに静的メソッドを直接呼び出すサードパーティのdepを導入すると、テストはいずれにせよ失敗します...
Jermy Krieg Fr

5

静的メソッドをモックする必要がある場合は、コードのにおいだと本気で思っています。

  • 共通機能にアクセスするための静的メソッド?->シングルトンインスタンスを使用し、それを注入します
  • サードパーティのコード?->独自のインターフェース/デリゲートにラップします(必要に応じてシングルトンにします)

これは私には行き過ぎと思われる唯一の時間は、グアバのようなLIBSですが、ロジックのそれの一部...(Iterables.transform(のようなもの。))を引き起こす種類とにかくこれを模擬する必要はありません
そのように独自のコードクリーンな状態を保ち、すべての依存関係をクリーンな方法でモックアウトでき、外部の依存関係に対する破損防止レイヤーがあります。PowerMockを実際に見たことがありますが、PowerMockに必要なすべてのクラスの設計が不十分でした。また、PowerMockの統合により、重大な問題が発生することもあります
(例:https : //code.google.com/p/powermock/issues/detail?id=355 )

PS:プライベートメソッドについても同様です。私はテストがプライベートメソッドの詳細について知っているべきではないと思います。クラスが非常に複雑で、プライベートメソッドをモックアウトしようとする場合は、おそらくそのクラスを分割する兆候です...


2
シングルトンは、特に実際に複数のインスタンスが必要であり、それを実現するためにシステム全体をリファクタリングする必要があることに気付いたときに、あらゆる種類の問題に遭遇します。
Ricardo Freitas 2017

私は誰にもシングルトンパターンをお勧めするとは言いませんでした。つまり、静的ユーティリティクラスと同じ機能を提供するシングルトンのどちらかを決定する必要がある場合は、シングルトンを選択します。そして、クラスがシングルトンかどうかにかかわらず、DIフレームワークで制御する必要がある場合は、クラスI @Inject SomeDependencyと構成で定義しますbind(SomeDependency.class).in(Singleton.class)。したがって、明日それがシングルトンではなくなった場合、1つの構成を変更すればそれだけです。
pete83 2017

@ pete83私はあなたの兄弟を聞きます。しかし、私はテストライブラリまたはフレームワークに問題があり、開発者がテストフレームワークの設計/制限を満たすように設計を変更する必要があります。それは、IMOがカートを馬の前に置くか、尾が犬を振るのです。
マットキャンベル

1
その議論は私にはほとんど意味がありません。シングルトンパターンは、ここに挙げることができないほど多くの理由により、ここ数年の間支持を失っています。「クリーン」コードを構成するものは何ですか?いくつかのI / O操作を返す静的ヘルパーメソッドを呼び出すクラスインスタンスメソッドがある場合、テストでそれをモックしたくないのはなぜですか?そして、その貧弱なデザインはどうですか?静的メソッドをモックするこの手書きのすべてが足し合わない。メソッドのモックは、テストの反対です。実装するの難しすぎる場合は、それを言ってそれで済ませる
eggmatters

ああ、私は誰もがFoo.getInstance()どこにでも電話するという古い学校のシングルトンパターンについて決して話しませんでした。「静的メソッドは多くのラッパーオブジェクトの作成を必要としない」という議論に対抗するために、答えにシングルトンを書いただけです。また、私にとって概念的には、シングルトンの静的メソッドとインスタンスメソッドの違いはほとんどありません。このシングルトンコラボレーターをモックすることはできません。しかし、シングルトンであるかどうかは、私が意図していたことではありません。コラボレーターを注入して模擬し、テストが困難な場合は静的メソッドを呼び出さないことが重要です。
pete83

4

Mockitoはオブジェクトを返しますが、静的は「オブジェクトレベルではなくクラスレベル」を意味するため、mockitoは静的に対してnullポインター例外を発生させます。


0

場合によっては、特にそれらをモックする必要がある場合、静的メソッドをテストするのが難しい場合があります。そのため、ほとんどのモックフレームワークは静的メソッドをサポートしていません。このブログ投稿は、静的メソッドとクラスをモックする方法を決定するのに非常に役立つことがわかりました。


1
静的メソッドのモックは、適切なモックAPIを使用すると、インスタンスメソッドのモックよりも簡単です(インスタンスがないため)。
ホジェリオ

これはだった質問自体、との質問に答えるようなもので、なぜこれが答えではないされている、そうすることは困難です。
Matthias

40
ブログの投稿では、クラスがたまたま使用する静的メソッドからクラスを分離する問題を実際に解決するのではなく、コストのかかる回避策(製品コードのリファクタリング)を推奨しているため、反対票を投じました。IMOは、実際に機能するモックツールであり、どのような方法も区別しません。開発者は、特定の状況で静的メソッドの使用の良し悪しを自由に決定できるのではなく、1つのパスに強制されるのではありません。
ホジェリオ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.