題名の通り。
PowerMock + Mockito で、
import java.lang.management.ManagementFactory; import javax.management.MBeanServer; import javax.management.ObjectName; ... ObjectName name = ObjectName.getInstance("my.pkg:type=xxyy,name=wwzz"); MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); mbs.invoke(name, "fooMethod", null, null);
この辺のコードをstubにしようとしたのだけれど、
ManagementFactory.getPlatformMBeanServer()
これをMockできない。
PowerMockito.mockStatic(ManagementFactory.class); MBeanServer mockMbs = Mockito.mock(MBeanServer.class); Mockito.when(ManagementFactory.getPlatformMBeanServer()).thenReturn(mockMbs);
コンパイルは通る。しかし、実行時に以下の例外が発生する。
org.mockito.exceptions.misusing.WrongTypeOfReturnValue: MBeanServer$$EnhancerByMockitoWithCGLIB$$911c39e9 cannot be returned by getPlatformMBeanServer() getPlatformMBeanServer() should return MBeanServer
MBeanServer周りなど独自のClassLoaderを使っているらしい。そのため、コンパイルは通ったとしても実行時にClassLoaderが分断されてしまい、クラス定義が見えなくなったり食い違ってしまうのが原因らしい。
参考:
古い話題ではなく、上記スレッドなど今年(2010)の5月頃。対処された様子も無い。
自分の技術力や、コピペだけでの回避が明らかに無理なので、今回は潔く敗北を認めた。しゃーない、
ManagementFactory.getPlatformBeanServer()を外に出して、MBeanServerをコンストラクタ経由で注入することで対処した。
今日一日で、随分とMockito + PowerMockでの地雷源を走った気がする。
いやね、ホントね、こう地雷ばっか踏んでると、紹介記事とかで「こんなに簡単にMockが作れちゃう!staticメソッドだってほら簡単!」とかね、ウソかと、コードが単純すぎないかと。
JMX周りのコードなんて、ちょっと込み入ったサービスやデーモン的なコード書こうと思えば出てくるのは確実なわけで。
で、ちょろっとそういう「現実の」ライブラリを使っただけでもう手に負えなくなるなんて、地雷原に嵌って何時間も英語含めてドキュメントだのGoogle検索だのして。
こんな面倒くさいのが「TDD」の「現実」だとすりゃ、そりゃ流行らねーわな。
コメント