PowerMockitoとは?静的・privateメソッドのMock化とMockitoネイティブへの移行判断
PowerMockitoは、モックライブラリPowerMockがMockito向けに提供するAPIで、通常のMockitoでは扱えない静的メソッド・コンストラクタ・privateメソッドをMock化するために使われてきました。ただし状況は2020年に大きく変わっています。Mockito 3.4以降は静的メソッドのMock化を本体だけで行えるようになり、いまPowerMockが本当に必要な場面は限られます。この記事では、PowerMockitoでの高度なMock化のやり方を実装例で示したうえで、どこまでをMockitoネイティブに置き換え、どこでPowerMockを残すべきかまで判断できるように整理します。テストを動かす土台となるJUnitの基礎はJUnitとはJava単体テストの基本・書き方を先に押さえておくと読み進めやすくなります。
まとめ
- PowerMockitoはPowerMockのMockito拡張。静的メソッド・コンストラクタ・privateメソッドという、素のMockitoで触れない領域を担当する。読みは「パワーモッキート」。
- 新規コードはMockito 3.4以降のネイティブ機能(mockStatic / mockConstruction)を第一候補にする。静的・コンストラクタのMock化だけならPowerMockは不要になった。
- PowerMockの最新は2.0.9(2020年公開)で更新が停滞し、JUnit 5を公式サポートしない。JUnit 4前提のプロジェクトに事実上ひも付く。
- それでもprivateメソッドのMock化はMockito本体では非対応で、ここだけはPowerMockの残存優位。ただし多くは設計の見直しで避けられる。
- 既存のPowerMockテストからの脱却は、OpenRewriteの自動移行レシピで機械的に置き換えられる部分が大きい。
以下、用語と使いどころの整理 → 導入と制約 → PowerMockitoの実装パターン → Mockitoネイティブへの移行判断、の順に解説します。
PowerMockとPowerMockito、Mockitoの関係と使いどころ
混同されやすい3つの名前を先に整理します。テスト対象のクラスに依存を差し込む基本操作は素のMockitoで完結し、PowerMockitoはその手が届かない特殊ケースだけを補う位置づけです。
PowerMock=本体、PowerMockito=Mockitoブリッジという関係
Mockitoは最も普及したJavaのモックライブラリで、インターフェースや通常のクラスのMock化・スタブ化を担います。PowerMockは独自のクラスローダとバイトコード操作で、Mockitoが設計上触れない静的メソッドなどをMock化する拡張ライブラリです。その中でMockitoのAPIスタイル(when/thenReturn)でPowerMockを呼ぶための入口がPowerMockitoで、読みは「パワーモッキート」です。つまり「Mockito+PowerMock」を使うとき、テストコードから叩くAPIがPowerMockitoにあたります。
PowerMockでしか扱えなかった4領域
素のMockitoが原則Mock化できず、PowerMockが担ってきたのは次の領域です。読者が「powermock mockito」「java powermock」で探すのは、たいていこのいずれかに当たります。
- 静的メソッド(
Utility.calc()のようなstaticメソッド) - コンストラクタ(
newで生成されるインスタンスの差し替え) - privateメソッド(外部から呼べない内部メソッドの検証・差し替え)
- finalクラス・finalメソッド(拡張・上書きできない型)
ただしこの前提は2020年に崩れています。finalと静的メソッドは、いまやMockito本体で扱えるためです。
新規の静的・コンストラクタはMockitoネイティブ採用が結論
先に判断を示します。これから書くテストで、PowerMockを静的・コンストラクタ・finalのために導入するのは避けるべきです。Mockito 3.4.0(2020年7月)で mockStatic()、3.5.0で mockConstruction() が本体機能として導入され(3.4〜4系は mockito-inline 依存、Mockito 5.0以降は mockito-core 既定)、finalのMock化も同様に本体で扱えるようになりました。PowerMockは専用ランナーとバイトコード書き換えを伴うため、JaCoCoのカバレッジ計測が崩れる、JUnit 5に載らない、といった副作用も抱えます。PowerMockが正当化されるのは「既存資産の保守」か「privateメソッドをどうしても直接Mock化したい」ケースにほぼ絞られます。
PowerMockitoの導入手順と前提バージョン
実装に入る前に、依存定義とバージョン制約を押さえます。ここを外すと動かないだけでなく、後述のJUnit 5非対応で行き詰まります。
依存定義(Maven/Gradle)とバージョンの組み合わせ
PowerMockitoはPowerMockのモジュールとして追加し、内部で使うMockitoのメジャーに合わせて powermock-api-mockito2 を選びます。最終リリースは2.0.9系です。PowerMock 2系はMockito 2〜3系と組み合わせる設計で、Mockito 4以降・5系とは公式に噛み合いません。裏を返すと、Mockitoを5系へ上げたい時点でPowerMockは足かせになります。Maven/Gradleの座標とMockitoのバージョン上限、PowerMockRunner の設定はPowerMockの@PrepareForTest指定ルールとPowerMockRunnerの設定手順にまとめてあります。
JUnit 4前提という制約(JUnit 5では動かない)
PowerMockは @RunWith(PowerMockRunner.class) というJUnit 4のRunnerモデルにMock化の仕組みを載せています。JUnit 5は拡張モデル(Extension)へ刷新されており、PowerMockはJUnit 5を公式サポートしていません。非公式ブリッジは存在しますが、保守されていないため実務では推奨しません。したがって「JUnit 5へ移行したい」「新規プロジェクトをJUnit 5で始める」場合、PowerMockは選択肢から外れ、Mockitoネイティブ一択になります。
PowerMockitoによる高度なMock化の実装パターン
PowerMockが担当するのは静的メソッド・コンストラクタ・privateメソッドの3領域です。前の2つは @PrepareForTest の指定さえ間違えなければ書けるため要点だけを示し、Mockito本体では今も代替できないprivateメソッドの検証を実装コードで扱います。
静的メソッドのMock化(mockStatic)
静的メソッドを差し替える手順は、対象クラスを @PrepareForTest に載せ、PowerMockito.mockStatic() で有効化してから when で戻り値を決める、という流れです。実装コードと verifyStatic による呼び出し検証の書き方はPowerMockの@PrepareForTest指定ルールとPowerMockRunnerの設定手順で扱っています。この用途はMockito 3.4以降なら本体だけで書けます(後述)。新規で静的メソッドのためだけにPowerMockを入れる理由は、もうありません。
コンストラクタのMock化(whenNew)
テスト対象の内部で new Clock() のように生成されるインスタンスを差し替えたい場合、PowerMockitoでは whenNew を使います。「powermockito whennew」で調べる人が詰まりやすいのが @PrepareForTest の対象で、newを呼ぶ側のクラスを指定しないと差し替えが効きません(生成される Clock 側ではありません)。指定ルールの全体像と実装例はPowerMockの@PrepareForTest指定ルールとPowerMockRunnerの設定手順を参照してください。
privateメソッドの呼び出し・検証(Whitebox)
外部から呼べないprivateメソッドを直接テストしたい場合、PowerMockの Whitebox.invokeMethod() でリフレクション経由で呼び出せます(invokeMethod は Exception を送出するため、テストメソッドに throws Exception を付けます)。カード番号のマスク処理 maskCard をprivateのまま検証する例です。
@Test
void カード番号をマスクする() throws Exception {
PaymentService service = new PaymentService();
String masked = Whitebox.invokeMethod(service, "maskCard", "1234-5678");
assertEquals("****-5678", masked);
}
privateメソッドのMock化・直接呼び出しは、Mockito本体では今も非対応です。ここがPowerMockに残る数少ない実利ですが、そもそもprivateを直接テストしたくなる時点で「テストしづらい設計」のサインでもあります。多くはpublicな入口経由の検証や、責務の分離(package-privateへの引き上げ)で解消でき、その判断はメンテナンス性を左右します。
PowerMockからMockitoネイティブへ移行する判断基準
ここが本記事の核心で、競合記事が手薄な論点です。「mockito-inlineとPowerMockitoの違い」「脱PowerMock」を検討している人向けに、置き換えの可否と手順を具体化します。
静的メソッドは mockStatic() で置き換える
先ほどのPowerMock版と同じ差し替えを、Mockito本体だけで書くとこうなります。mockStatic() は MockedStatic を返し、try-with-resourcesのスコープ内でだけMockが有効になる点がPowerMockとの大きな違いです。テスト間でMockが漏れず、スレッド単位で閉じられます。
@Test
void 税込価格を返す() {
try (MockedStatic<PricingUtil> mocked = mockStatic(PricingUtil.class)) {
mocked.when(PricingUtil::taxRate).thenReturn(0.10);
OrderService service = new OrderService();
assertEquals(1100, service.total(1000));
}
}
依存はMockitoのバージョンで変わります。Mockito 3.4〜4系は mockito-inline を追加する必要があり、Mockito 5.0(2023年)以降は inline mock maker が mockito-core の既定になったため mockito-inline は不要です(Java 11以上が前提)。「mockito inline」で検索して依存が見つからない場合、Mockito 5系に上げていればそれが正常です。
コンストラクタは mockConstruction() で置き換える
whenNew に相当するコンストラクタのMock化も、Mockito 3.5以降は mockConstruction() で書けます。スコープ内で new されたインスタンスに一括でスタブを適用します。
@Test
void ヘッダー日時を固定する() {
try (MockedConstruction<Clock> mocked = mockConstruction(Clock.class,
(mock, ctx) -> when(mock.now()).thenReturn("2026-01-01"))) {
assertEquals("2026-01-01", new ReportService().header());
}
}
「mockedconstruction」で本記事に流入する人が求めているのはこの形です。@PrepareForTest も専用ランナーも要らず、JUnit 5でそのまま動きます。静的・コンストラクタのMock化が目的なら、この2つでPowerMockの主要用途はカバーできます。
PowerMockを残すケースとOpenRewriteによる自動移行
すべてが置き換わるわけではありません。privateメソッドの直接Mock化・呼び出しと、膨大なJUnit 4資産をすぐには動かせないケースは、当面PowerMockを残す合理性があります。逆に静的・コンストラクタ・finalが主目的なら移行して問題ありません。
移行を手作業でやる必要はありません。OpenRewriteには「Replace PowerMock with raw Mockito」に相当するレシピがあり、mockStatic/mockConstruction への置き換えやアノテーション除去を機械的に適用できます。まずこのレシピを流し、privateメソッド絡みなど自動変換できなかった箇所だけを手当てする、という順序が現実的です。段階的に移せば、Mockito 5系・JUnit 5への更新経路も開けます。移行後はテストの網羅度が落ちていないか、テストカバレッジのC0/C1/C2網羅率で確認しておくと安全です。
よくある質問
PowerMockitoの読み方は?
「パワーモッキート」と読みます。Mockito(モッキート)に、能力を意味するPower(パワー)を冠した名称です。表記は「PowerMockito」で、ライブラリ本体はPowerMock、そのMockito向けAPIがPowerMockitoです。
PowerMockはJUnit 5で使えますか?
公式には使えません。PowerMockはJUnit 4のRunner(@RunWith(PowerMockRunner.class))に依存し、JUnit 5の拡張モデルを公式サポートしていません。JUnit 5環境では、静的・コンストラクタのMock化はMockitoネイティブの mockStatic()/mockConstruction() に置き換えるのが正攻法です。
mockito-inlineとPowerMockitoの違いは?
mockito-inlineはinline mock makerを有効化するMockito公式のアーティファクトで(Mockito 5.0以降は mockito-core に統合され追加不要)、静的メソッド・finalのMock化をMockitoのAPIだけで行います。スコープ限定で安全、JUnit 5対応、カバレッジ計測とも相性が良いのが利点です。PowerMockitoは独自クラスローダで同じことをより広く(privateまで)実現しますが、JUnit 4前提で更新も停滞しています。privateメソッドが要らなければmockito-inline側で足ります。
privateメソッドはMock化すべきですか?
原則は避けるべきです。privateを直接Mock化・検証したくなるのは、そのクラスの責務が過大というサインが多く、publicな入口からの検証やクラス分割で解けるのが理想です。どうしても必要ならPowerMockの Whitebox で呼び出せますが、Mockito本体は非対応で、テストが実装詳細に密結合しやすい点を織り込んで判断してください。
PowerMockの最新バージョンとメンテナンス状況は?
最新は2.0.9系で、2020年の公開以降は目立った機能追加が止まっています(最新はMaven Centralで確認してください)。Mockito 2〜3系との組み合わせが前提で、Mockito 4・5系やJUnit 5には追随していません。新規採用より、既存テストの保守と段階的な脱PowerMockを前提に扱うのが妥当です。