---
title: "PowerMockの@PrepareForTest指定ルールとPowerMockRunnerの設定手順"
url: "https://www.issoh.co.jp/tech/details/3637/"
published: 2024-09-24
updated: 2026-08-04
categories: ["Java"]
publisher: "株式会社一創"
---

# PowerMockの@PrepareForTest指定ルールとPowerMockRunnerの設定手順

PowerMockitoでつまずく箇所は、APIの書き方よりも**@PrepareForTestにどのクラスを書くか**に集中します。指定を1つ間違えるだけで、モックが素通りして実メソッドが走り、テストは「なぜか本物が呼ばれる」状態で落ちます。ここでは@PrepareForTestの指定ルール、PowerMockRunnerと依存定義、静的メソッドの検証記法を、公式wikiとソースコードの記述で整理します。PowerMockitoそのものの位置づけやMockitoネイティブへ移行すべきかの判断は、[PowerMockitoとは？静的・privateメソッドのMock化とMockitoネイティブへの移行判断](/tech/details/2351/)にまとめてあります。

## まとめ

- @PrepareForTestには原則として**モック対象の静的メソッドを定義しているクラス**を書きます。
- 例外は2つです。`java.*`などのシステムクラスと、`whenNew`によるコンストラクタのモックでは**呼び出す側（newする側）のクラス**を指定します。
- 依存はPowerMockの2アーティファクトに加えてMockito本体とJUnit 4が必要です。PowerMock 2.0.9はmockito-core 3.3.3でビルドされているため、Mockitoは2.8.9以上3.x系までに収めます。
- `verifyStatic`は「verifyStaticでクラスを指定する行」と「検証したい静的メソッドを書く行」の2行で1組です。引数なしの`verifyStatic()`は2.0で削除されており、2.x系ではコンパイルできません。
- PowerMockの最終リリースは2.0.9（2020年11月2日）、リリースブランチの最終コミットは2022年2月24日です。JUnit 5対応モジュールは提供されていません。

## @PrepareForTestに指定するクラスの決め方

### 静的メソッドを定義しているクラスの指定

PowerMockは、指定されたクラスを専用のクラスローダで読み込み直し、バイトコードを書き換えることで静的メソッドやfinalメソッドを差し替えます。したがって**書き換えたい定義そのものを持つクラス**が指定対象です。`TaxTable.rateOf()`という静的メソッドをモック化したいなら、`@PrepareForTest(TaxTable.class)`と書きます。複数クラスをまとめて準備する場合は`@PrepareForTest({TaxTable.class, RateLoader.class})`のように配列で渡します。

| モックしたい対象           | @PrepareForTestに書くクラス |
| ------------------ | --------------------- |
| 通常の静的メソッド          | そのメソッドを定義しているクラス      |
| finalメソッド・finalクラス | そのメソッドを定義しているクラス      |
| privateメソッド        | そのメソッドを持つテスト対象クラス     |
| システムクラス（java.\*）   | それを呼び出す側のクラス          |
| コンストラクタ（whenNew）   | newを実行する側のクラス         |

```
@RunWith(PowerMockRunner.class)
@PrepareForTest(TaxTable.class)
public class InvoiceServiceTest {

    @Test
    public void 軽減税率の対象なら8パーセントで計算する() {
        PowerMockito.mockStatic(TaxTable.class);
        Mockito.when(TaxTable.rateOf("FOOD")).thenReturn(8);

        InvoiceService service = new InvoiceService();
        Assert.assertEquals(1080, service.totalOf("FOOD", 1000));
    }
}
```

### システムクラスとwhenNewで指定対象が入れ替わる条件

公式wikiがこの2ケースだけ別ページを立てて例外扱いしており、指定対象が反転するのはここだけです。システムクラスについてwikiは「通常はモックしたい静的メソッドを含むクラス（Xとする）を準備するが、PowerMockがシステムクラスをテスト用に準備することは不可能なので別の方法を取る。Xを準備する代わりに**Xの静的メソッドを呼び出しているクラス**を準備する」と説明しています。`URLEncoder.encode()`や`System.currentTimeMillis()`をモック化するなら、指定するのは`URLEncoder.class`ではなく、それを呼んでいる自分のクラスです。

コンストラクタのモック（`whenNew`）も同じ向きになります。wikiは`new File(..)`の例で「`File.class`を準備しないのは、`expectNew`のときFileの新しいインスタンスが決して生成されず、PowerMockは**newを実行するクラス**からのnew呼び出しを横取りするだけだからだ」と述べています。`new`を書いた側のクラスを指定してください。

```
@RunWith(PowerMockRunner.class)
@PrepareForTest(ReportWriter.class)
public class ReportWriterTest {

    @Test
    public void 出力先ファイルの生成を差し替える() throws Exception {
        File dummy = Mockito.mock(File.class);
        PowerMockito.whenNew(File.class).withArguments("report.csv").thenReturn(dummy);

        new ReportWriter().write("report.csv");
        Mockito.verify(dummy).createNewFile();
    }
}
```

`withArguments`には、`ReportWriter`が実際に`new File(...)`へ渡す引数をそのまま書きます。ここを`@PrepareForTest(File.class)`に変えると、`whenNew`が効かずに実ファイルが作られたうえ、`verify`が「Wanted but not invoked」で落ちます。原因がモックの指定ミスだと気づきにくい落ち方なので、モックが効かないときは指定したクラスが「定義側」か「呼び出し側」かを先に確認してください。

## PowerMockRunnerと依存定義の設定手順

### Maven／Gradleで揃える依存とMockitoの上限

PowerMockitoは単体では動きません。JUnit 4と結合するモジュール、Mockitoへのブリッジ、Mockito本体、JUnit 4本体の4つを揃えます。注意すべきはMockito側の上限です。`powermock-2.0.9`タグのbuild.gradleは`mockitoVersion = "3.3.3"`と`junitVersion = "4.12"`を宣言しており、公式wikiの対応表も「Mockito 2.8.9以降＝PowerMock 2.x」という行で止まっています。Mockito 4系・5系との対応は公式に示されていないため、3.x系までに固定するのが安全です。

```
<dependencies>
  <dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-module-junit4</artifactId>
    <version>2.0.9</version>
    <scope>test</scope>
  </dependency>
  <dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-api-mockito2</artifactId>
    <version>2.0.9</version>
    <scope>test</scope>
  </dependency>
  <dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-core</artifactId>
    <version>3.3.3</version>
    <scope>test</scope>
  </dependency>
  <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.13.2</version>
    <scope>test</scope>
  </dependency>
</dependencies>
```

```
testImplementation 'org.powermock:powermock-module-junit4:2.0.9'
testImplementation 'org.powermock:powermock-api-mockito2:2.0.9'
testImplementation 'org.mockito:mockito-core:3.3.3'
testImplementation 'junit:junit:4.13.2'
```

テストクラス側は`@RunWith(PowerMockRunner.class)`を付けるだけです。JUnit本体の書き方は[JUnitの基本と書き方をまとめた記事](/tech/details/3064/)で確認できます。

### @PowerMockRunnerDelegateによる他Runnerとの併用

JUnit 4のRunnerはクラスに1つしか付けられません。`SpringJUnit4ClassRunner`や`Parameterized`を使っているテストにPowerMockを足すと、ここで衝突します。解決策は、PowerMockRunnerを外側に置き、本来のRunnerを`@PowerMockRunnerDelegate`に委譲する形です。

```
@RunWith(PowerMockRunner.class)
@PowerMockRunnerDelegate(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = TestConfig.class)
@PrepareForTest(TaxTable.class)
public class InvoiceServiceSpringTest {
}
```

## 静的メソッドのMock化と呼び出し検証の書き方

### mockStatic後の既定値とスタブ定義に使うwhen

`PowerMockito.mockStatic(X.class)`を呼んだ時点で、Xの静的メソッドはすべて既定値（オブジェクトはnull、intは0）を返すようになります。スタブしていない静的メソッドが`null`を返してNullPointerExceptionになるのは、この挙動が原因です。

戻り値の指定には通常の`Mockito.when`を使います。`PowerMockito`にも同じシグネチャの`when(T methodCall)`がありますが、こちらの本来の役目は`when(Object instance, String methodName, Object... arguments)`のようなprivateメソッド向けオーバーロードの提供です。静的メソッドのスタブでどちらを書くか迷ったら、Mockito側に寄せておけば読み手の負担が減ります。モックとスタブの役割の違いは[モックとスタブの違いとテストダブルの5分類を解説した記事](/tech/details/13505/)で整理しています。

### verifyStaticの2行イディオム

PowerMock 2系の`verifyStatic`は、引数に検証対象のメソッド呼び出しを渡す形式ではありません。**「verifyStaticでクラスを指定する行」と「検証したい静的メソッドを書く行」の2行で1組**です。1行にまとめて書くと、検証がまったく行われないまま成功します。

```
PowerMockito.verifyStatic(TaxTable.class, Mockito.times(1));
TaxTable.rateOf("FOOD");
```

2行目は実処理として走るのではなく、検証したいメソッドの指定として解釈されます。回数指定を省いた`verifyStatic(TaxTable.class)`は、ソース上も`verifyStatic(mockedClass, times(1))`を呼ぶだけのエイリアスです。なお1.7系で非推奨だった引数なしの`verifyStatic()`は2.0で削除され、2.xの`PowerMockito`には`Class`を取る2つのオーバーロードしか残っていません。旧コードを持ち込むとコンパイルが通らない点に注意してください。

## PowerMockのバージョン互換とメンテナンス状況

### 最終リリース2.0.9とリリースブランチの停止時期

依存を固定する前に、プロジェクトの現状を数字で押さえておく価値があります。GitHubのリリース情報では、PowerMockの最新リリースは**2.0.9で公開日は2020年11月2日**です。既定ブランチ`release/2.x`の最終コミットは2022年2月24日で、内容はMockito 4.3.1との互換を取るプルリクエスト（#1113）でした。**この変更はリリースされていないため、公開済みのアーティファクトはMockito 4系に対応していません。**リポジトリはアーカイブされていないものの、5年以上リリースが出ていない状態が続いています。

新しいJDKへの追随も止まっています。`powermock-2.0.9`タグのbuild.gradleが宣言するバイトコード操作ライブラリは`javassist 3.27.0-GA`・`byte-buddy 1.10.14`・`objenesis 3.0.1`で、いずれもJDK 17の一般提供（2021年9月）より前の版に固定されています。JDKを上げた直後にテストだけが落ちる場合、まずこの固定を疑ってください。

### JUnit 5対応が入っていない経緯

PowerMockにJUnit 5用のモジュールはありません。公式リポジトリでは`Support jUnit5`というissue（#830）が2017年8月7日に作成され、現在もopenのままです。同趣旨のissueは2018年（#929）、2022年（#1129）にも立っています。JUnit 5へ移行するプロジェクトでPowerMockを残す選択肢は事実上ないため、テストをJUnit 4に据え置くか、静的メソッドのモックをMockito側へ寄せるかの二択になります。

### Mockito 5系ではPowerMockを併用できない条件

Mockito側は、3.4.0（2020年7月10日）のリリースノートに「Enable mocking static methods in Mockito」と記載し、静的メソッドのモックを自前で提供しています。5.0.0（2023年1月14日）ではinline mock makerが既定になり、最低要件はJava 11以上へ引き上げられました。従来のsubclass mock makerは`mockito-subclass`という別アーティファクトに分離されています。最新は5.23.0（2026年3月11日リリース）です。

公開済みのPowerMock 2.0.9はmockito-core 3.3.3を前提にビルドされているため、Mockito 5系を採用した時点でPowerMockとの併用は成立しません。「PowerMockを足すかどうか」ではなく、**静的メソッドは標準の`mockStatic`へ寄せる、privateメソッドへの依存が残るならMockito 3.x系に据え置いてテスト設計を見直す**、という二択で考えます。判断の分かれ目は[Mockitoネイティブへの移行判断をまとめた記事](/tech/details/2351/)で条件別に整理しています。

## よくある質問

### @PrepareForTestには複数のクラスを指定できますか？

指定できます。公式wikiのシステムクラスの例も`@PrepareForTest( { SystemClassUser.class })`と波かっこで書かれており、値は配列です。ただし準備したクラスは専用クラスローダで読み直されるため、必要なクラスだけに絞るほうがテストは安定します。

### PowerMockRule（@Rule）はRunnerの代わりに使えますか？

Runnerを他のフレームワークに占有されていて`@PowerMockRunnerDelegate`も使えない場合の選択肢になります。`powermock-module-junit4-rule`に加えて`powermock-classloading-xstream`または`powermock-classloading-objenesis`の追加が必要で、クラスローダの切り替え方もRunner方式と変わります。Runnerで動く構成ならRunnerのままにしておくほうがトラブルは少なくなります。

### JaCoCoでカバレッジが計測されなくなるのはなぜですか？

@PrepareForTestの対象クラスがPowerMock独自のクラスローダで読み直され、JaCoCoエージェントによる実行時のクラス書き換えが反映されないためです。対象クラスのカバレッジが0%と表示されることがあります。JaCoCo公式は、オフラインインストルメンテーションが必要になるケースとして「動的にクラスファイルを変換する他のエージェントとの衝突」を挙げており、回避策はオフラインインストルメンテーションへの切り替えか、対象クラスを準備対象から外すことです。テスト網羅の指標そのものは[バグ密度・テスト密度の目安を扱った記事](/tech/details/9894/)を参照してください。

### Mockitoの`when`だけでは静的メソッドをモック化できないのはなぜですか？

Mockitoの`when`はモックインスタンスへの呼び出しを記録する仕組みで、インスタンスを介さない静的メソッドは記録対象になりません。静的メソッドを扱うには、PowerMockitoの`mockStatic`か、Mockito 3.4.0以降の`Mockito.mockStatic`が返すスコープ付きモックが必要です。

### 「モック化」はスタブとどう違いますか？

スタブは決められた値を返すだけの代役、モックは呼び出され方まで検証できる代役という区別が一般的です。PowerMockitoの`mockStatic`と`verifyStatic`は、この「呼び出され方の検証」までを静的メソッドに対して行うためのAPIにあたります。分類の詳細は[テストダブルの5分類を解説した記事](/tech/details/13505/)にまとめてあります。

## 関連記事

- [PowerMockitoとは？静的・privateメソッドのMock化とMockitoネイティブへの移行判断](/tech/details/2351/)
- [JUnitとは？Javaの単体テストフレームワークの基本と書き方【2026年版】](/tech/details/3064/)
- [モックとは？スタブとの違い・テストダブル5分類と単体テストでの使い分けを実装者向けに解説](/tech/details/13505/)
- [テストピラミッドとは？単体・結合・E2Eの配分と実装者向けテスト戦略設計](/tech/details/13289/)
- [バグ密度・テスト密度の目安｜IPA基準値と計算式・ゾーン分析](/tech/details/9894/)

---

出典: [PowerMockの@PrepareForTest指定ルールとPowerMockRunnerの設定手順](<https://www.issoh.co.jp/tech/details/3637/>)（株式会社一創）
