1. ホーム
  2. java

[解決済み] PowerMock + Mockito VS Mockito単体

2022-03-11 23:05:03

質問

Mockitoの上にPowerMockを追加すると、具体的にどのような機能があるのか、どなたかまとめていただけませんか?

今のところ、これらが見つかりました。

  • static、final、private メソッドをモックする
  • 静的イニシャライザーの削除
  • 依存性注入なしでモッキングを許可する - これは私にとって明確ではありません。詳しく説明してもらえますか?

他に何か追加されるのでしょうか?数行でまとめていただけませんか?

また、PowerMockを使用する場合、何かを犠牲にする必要があるのでしょうか?

どのように解決するのですか?

他の利点はすぐにはわかりませんが、あなたのサブクエスチョンのうちの2つを取り上げたいと思います(これはコメントとしては長すぎますね)。

<ブロッククオート

依存性注入を行わずにモッキングを可能にする - これは私には明確ではありません。詳しく説明していただけますか?

からきていると思います。 モチベーションwikiページ ここでは、テスト可能にするために、静的メソッドを呼び出さないようにコードをリファクタリングする方法について説明しています。具体的な例として、このようなコードがあって、 powermock を使わずに静的メソッドの振る舞いをモックするメソッドをテストしたいとします。

public class MyClass {
     public void doGetString() {
         ...
         OtherClass.getString(); //It's complex and scary and needs mocking!
         ...
     }
}

一つの解決策は、静的な呼び出しをそれ自身のオブジェクトに引き込み、テスト時にモックできるオブジェクトを注入することでしょう。例えば、他のフレームワークを使用しない場合、次のようになります。

public class MyClass {
     public static class StringGetter {
         public getString() {
             return OtherClass.getString();                 
         }
     }

     private final StringGetter getter;

     //Existing Constructor
     public MyClass() {
         this(new StringGetter());
     }

     //DI Constructor
     MyClass(StringGetter getter) {
         this.getter = getter;
     }

     public void doGetString() {
         ...
         getter.getString();
         ...
     }
}

自分のメソッドの挙動と静的な呼び出しの挙動を分離し、DI コンストラクタを使ってテスト時に簡単にモックを注入できるようになりました。もちろんpowermockを使えば、静的メソッドをそのままモックして実行することもできます。

<ブロッククオート

また、PowerMockを使用する場合、何かを犠牲にする必要がありますか?

物理的にはノーですが、哲学的にはイエスです :) 。以下は私の意見であり、その背景には十分な理由があるつもりですが、もちろん意見ですので、大目に見てください。

PowerMockで起きている潜在的に恐ろしいことは、プライベートおよびスタティックメソッドをモックするという偉業を達成するために、カスタムのクラスローダー(本番環境では実行時に存在しないはず)を使用し、クラスのバイトコードを変更していることです。しかし、もしバイトコードが変更され、特定の副作用がなくなった場合、既存のクラスに基づいてはいるものの、事実上異なるクラスをテストしていることになります。そう、これは非常に学術的な議論なのです。

この最初の議論は、PowerMockを使わない包括的な統合テストやより高度なテストを用意することで、ある程度軽減することができます。こうすることで、ユニットテストがPowerMockを使用していても、オブジェクトの動作にもっと自信を持つことができるのです。

PowerMockに反対するもう1つの理由は、あまりにも簡単に松葉杖になってしまうということです。PowerMockがレガシーコードやコントロールできないコードを使用するテストに役立つということには同意します。しかし、モックにする必要があるクラスをコントロールできる場合は、PowerMockの使用を避けるべきだと主張します。もし、他のメソッドをテストするために明示的にモックする必要があるプライベートメソッドやスタティックメソッドを持つクラスを書いたとしたら、私の直感では、このメソッドはやりすぎで、リファクタリングして分割した方が良いのではないかと思います。PowerMockがすでにプロジェクトで利用可能であれば、モックだけ作って先に進みたくなるかもしれませんし、同じようにリファクタリングする痛みを軽減することができるはずです。技術的、非技術的に様々な制約があるため、これができない場合もありますが、ペインポイントを避けるのではなく、解決するのは良いことです:)