MockK と JMockit の組み合わせで AttachNotSupportedException 例外が発生することがあるっぽい
Kotlin で Mockito を使うのが辛くなってきた *1 ので、「よーしパパ MockK 入れちゃうぞー」 と言って MockK 1.8.12 を導入したのだけど、その結果テストを実行すると以下のような初期化エラーが発生するようになってしまった。
java.lang.ExceptionInInitializerError at MyTest.<init>(MyTest.kt:101) Caused by: java.lang.IllegalStateException: Error during attachment using: net.bytebuddy.agent.ByteBuddyAgent$AttachmentProvider$Compound@718207 at net.bytebuddy.agent.ByteBuddyAgent.install(ByteBuddyAgent.java:384) at net.bytebuddy.agent.ByteBuddyAgent.install(ByteBuddyAgent.java:358) at net.bytebuddy.agent.ByteBuddyAgent.install(ByteBuddyAgent.java:326) at net.bytebuddy.agent.ByteBuddyAgent.install(ByteBuddyAgent.java:312) at io.mockk.proxy.jvm.JvmMockKAgentFactory.initInstrumentation(JvmMockKAgentFactory.kt:122) at io.mockk.proxy.jvm.JvmMockKAgentFactory.init(JvmMockKAgentFactory.kt:31) at io.mockk.impl.JvmMockKGateway.<init>(JvmMockKGateway.kt:45) at io.mockk.impl.JvmMockKGateway.<clinit>(JvmMockKGateway.kt:163) ... 22 more Caused by: java.lang.reflect.InvocationTargetException at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:497) at net.bytebuddy.agent.Attacher.install(Attacher.java:84) at net.bytebuddy.agent.ByteBuddyAgent.install(ByteBuddyAgent.java:379) ... 29 more Caused by: com.sun.tools.attach.AttachNotSupportedException: no providers installed at com.sun.tools.attach.VirtualMachine.attach(VirtualMachine.java:208) ... 35 more
スタックトレースの一番下を見ると com.sun.tools.attach.VirtualMachine
なので、JDK の内部でなんかなってるのかなー、と最初は思っていたのだけど、IDE で辿っていくと VirtualMachine
クラスは JMockit に含まれているものだということがわかった。 使っていた JMockit が 1.22 と少し古いものだったので、最新の 1.43 を使うようにしたら無事エラーは発生しなくなった。
Mockito でも同様のエラーが発生することがある模様。
ちなみに com.sun.tools.attach.VirtualMachine
は、JVM にアタッチするための API に含まれるものらしい。