Closed tt-kuma closed 4 years ago
モック使用時のバグを再現するための簡単なプロジェクトを作りました. zipファイルを解凍後,README.mdファイルを読んでください.
このissueのゴールって「再現する最小の題材を作る」でしたね. 作った題材でプルリクを送ります.
あ,mergeするものがないからプルリク無理でした.あたりまえか...
題材確認しました.
題材が単体で動作しません.
java.lang.IllegalStateException: Could not initialize plugin: interface org.mockito.plugins.MockMaker (alternate: null)
at org.mockito.internal.configuration.plugins.PluginLoader$1.invoke(PluginLoader.java:74)
...
おそらくmockitoの依存libの不足が原因です.
net.bytebuddy » byte-buddy
net.bytebuddy » byte-buddy-agent
org.objenesis » objenesis
https://mvnrepository.com/artifact/org.mockito/mockito-core/3.2.4
依存libがないので,題材の実行ができず, 結果的にkgpが失敗している(ように見える),という状態だと思います.
byte-buddy と objenesis を追加しました. もう一度試して頂けますか.
後のための備忘録
mock題材をkgpが正しく処理できないことを確認.
→ no ビルド自体は成功
→ yes
TestThread
のテスト実行失敗時にdebugログを入れた.
2020-03-16 12:53:55 [main] [WARN] TestThread - java.lang.LinkageError: loader constraint violation: loader 'app' wants to load interface org.hamcrest.Matcher. A different interface with the same name was previously loaded by jp.kusumotolab.kgenprog.project.test.SkippingMemoryClassLoader @7cd1ac19. (org.hamcrest.Matcher is in unnamed module of loader jp.kusumotolab.kgenprog.project.test.SkippingMemoryClassLoader @7cd1ac19, parent loader 'app')
at java.base/java.lang.ClassLoader.defineClass1(Native Method)
at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1016)
at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:174)
at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.java:800)
at java.base/jdk.internal.loader.BuiltinClassLoader.findClassOnClassPathOrNull(BuiltinClassLoader.java:698)
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:621)
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:579)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:12)
at org.junit.Assert.assertThat(Assert.java:956)
at org.junit.Assert.assertThat(Assert.java:923)
at smt.SimpleMockitoTest.testMockitoMain(SimpleMockitoTest.java:17)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:52)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.FailOnTimeout$CallableStatement.call(FailOnTimeout.java:303)
at org.junit.internal.runners.statements.FailOnTimeout$CallableStatement.call(FailOnTimeout.java:297)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at java.base/java.lang.Thread.run(Thread.java:834)
クラスロードの問題らしい.
org.hamcrest.Matcher
を app
がロードしようとしたけど,
SkippingMemoryCL
がロード済みでまずい,とのこと.
SMCL
のロードスキップ条件を追加してみた.
- if (name.startsWith("org.junit.") || name.startsWith("junit.")) {
+ if (name.startsWith("org.junit.") || name.startsWith("junit.") || name.startsWith("org.hamcrest.")) {
このロードスキップ処理は #554 で追加された. JUnit関連のロードのみをAppClassLoaderに委譲するらしい.
SkippingMemoryClassLoader
MemoryClassLoaderの拡張クラス.クラスローダの委譲関係をあえて崩すことで,KGP本体のクラスロード(
AppClassLoader
)の副作用を回避する.委譲の流れは以下の通り.- SkippingMemoryClassLoader -> AppClassLoader (ここをスキップ) -> ExtensionClassLoader (ここにダイレクトに委譲) -> BootstrapClassLoader
ただし例外としてJUnit関係のクラスのみ,そのロードをAppClassLoaderに委譲する.KGPのテスト実行時のJUnitクラス,及び題材のテスト実行時のJUnitクラスを同一のクラスローダでロードしないと,JUnitが期待通りに動作しないため.
とりあえず上の対応でうまく動いていることを確認. もう少しデバッグしておくべき.