PowerMockとJUnitのRuleを使うときのメモ
少し試行錯誤してしまったので書いときます。この情報はバージョンによって古くなる可能性が十分にあります。
- PowerMock: 1.5
- Mockito: 1.9.5
- junit: 4.11
short answer
PowerMockRule は使わず PowerMockRunner を使いましょう。
PowerMock?
いわゆるMockのアレですが、名前の示す通りPowerある感じです。staticとかをアレできるところとかが。使い方はJUnitのRunnerで指定するのが基本です。
@RunWith(PowerMockRunner.class) @PrepareForTest(Fuga.class) public class HogeTest { //... }
これの良いところは「うわーまたMockの使い方覚えなきゃなのかよ……」なんて私のために、MockitoやEasyMockの形で書けるところです。PowerMockito とか見ればわかるように Mockito クラスの代わりに PowerMockito を使えばだいたいそんなノリで使えます。どっちをstatic-importしたか忘れる事もしばしばありますが、それで困った記憶はあまり無いです。
Runner を使いたくない
JUnit4 以降を使うことで継承の呪縛から解き放たれた我々ですが、依然として一つのものしか使えない特権階級が居ます。それが @RunWith で指定する Runner さん。Runner さんをいじると色んな事が出来て万能感あるのですが、使えるのは一つだけになってしまう辺り残念な感じになります。なので出来るなら Rule で閉じて Runner は最後の手段に置いておきたい。
PowerMockRule がある
Rule さんを用意してくれてます。
@PrepareForTest(Fuga.class) public class HogeTest { @Rule public PowerMockRule rule = new PowerMockRule(); //... }
わるくない。*1公式のWikiでは PrepareForTest アノテーションの後ろにセミコロンが入ってたり、Rule が public でなかったりで、コピペじゃ動きません。ハードルたけぇ。
いい感じな気がしたのですが、これ……複数Rule指定すると動かなくなります。同じような人居ました。
JUnit4.7で追加された MethodRule さんですが、JUnit4.9で TestRule さんが追加され、これに置き換えられていく感じでございます。
* Note that {@link MethodRule} has been replaced by {@link TestRule},
* which has the added benefit of supporting class rules.
Rule にはJUnit4.9以降 @Rule と @ClassRule ができて MethodRule は合わなくなっちゃったんだけど、名前変更じゃなく追加なのは MethodRule を自分で実装しちゃってる人も結構いたからなんでしょうね。公開インタフェースは難しいです。
と言うことで結論
JUnitを使って Rule を使わないなんて選択は呼吸困難に陥るので、生命維持のために「PowerMockRule は使えない」になります。
PowerMock を使うときは PowerMockRule は使わず PowerMockRunner を使いましょう。
@RunWith(PowerMockRunner.class) @PrepareForTest(Fuga.class) public class HogeTest { @Rule public ExpectedException ex = ExpectedException.none(); //... }
どっちも Rule で出来ればよかったんだがな……(´・ω・`)
余談: RuleChain さん
Rule の順序をハッキリさせられる RuleChain さんがJUnit4.10 で追加されているのですが、これ TestRule しか見てくれません。MethodRule は使っちゃダメですね。その辺を気にせずまとめて Rule と認識して RuleChain さんを使おうとすると、コンパイル出来なくて首を傾げる事になります。ここに書いている事は忘れて私と一緒に首を傾げましょう。
*1:使わないRuleフィールドを宣言しなきゃいけないのは筋が悪い気もしてる今日この頃。