home Glamenv-Septzen(ぐらめぬ・ぜぷつぇん)(archive)

技術/TDD/Javaでstaticメソッドをmockする

作成日: 2013-07-27 21:38:45   /   last updated at: 2013-07-27 21:59:24
カテゴリ: Java TDD プログラミング 

powermockがオススメ・・・というか他に知らないんですが。ただし、staticメソッドやSystem ClassLoaderによりロードされるJDKコアクラスをmockする必要が発生する場合、それ以前の問題としてそもそもアーキテクチャが不味くてリファクタリングした方が良いような状況だったりします。後述しますが、可能な限りstaticメソッドのmockやJDKコアクラスをmockする手法は避けてください。ぶっちゃけ地雷原です。

メリットを遥かに上回る(というか実際トラブルで嵌る)デメリット群:

  • staticメソッドのmockやシステムクラスのmockを使いはじめると、JUnitなどのテストランナーを"@RunWith"を指定してpowermockが提供する専用のクラスローダ上で動かす必要があったりします。そのため、他に"@RunWith"アノテーションが必要なテストライブラリを併用する場合に不都合が出てくるかもしれません。
  • 内部的には独自クラスローダの中でバイトコードを操作してmock専用のクラスを動的に構築するなど、かなり「ゴツイ」処理を行なっています。そのため、クラスの構成や処理内容によっては、思わぬ所で副作用が発生し、非常に原因究明の難しいエラーが発生する場合があります。 というか、ありました。 (具体的な内容は忘れましたが。)
  • クラスローダ周りのトラブルはJVMのバイトコードのVerifierとか、JDKのClassLoaderの内部処理など相当低レイヤーで追うのが難しい領域で発生し、StackTraceのメッセージだけでは何が起こっているのかすら分からないことがあります。
    • → 一度トラブルになると、それを収めるのに相当な時間を費やすことになる可能性が高いです。

ということで、個人的にはstaticメソッドやJavaのシステムクラスをmockしたいような場合、powermockを使って頑張ってmockするのではなく、以下の様な妥協案を探ることをオススメします。

  1. リファクタリングでstaticメソッドを追い出したり、
  2. システムクラスの処理をラップしてmockしやすくしたり、
  3. そこまでセンシティブなコードは自動化を諦める、など。

以下の記事を読んでみると、staticメソッドやSystem ClassLoaderにより読み込まれるJDKコアクラスをmockするのがどれほどセンシティブな処理であるか理解いただけるかと。


original url: https://www.glamenv-septzen.net/view/1227