今天在Spring Boot + Gradle新的專案執行JUnit測試時,出現java.lang.NoClassDefFoundError
的錯誤,過程及原因如下。
先說結論,造成錯誤的原因是在Gradle專案的build.gradle
引入了不存在的依賴函式庫。
今天(2019/8/30)根據Apache Commons Numbers的Github頁面說明,其Maven Central位置如下:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-numbers</artifactId>
<version>1.0</version>
</dependency>
但之後不論在Maven Central或透過Maven都無法從上述的位置下載,也就是被Apache Commons Numbers的Github說明給唬了。
因此我根據上面的資訊在Spring Boot + Gradle新專案的build.gradle
設定了以下試圖引入依賴函式庫。因為是新的專案,所以只是先引進來以後可以使用。
dependencies {
...
implementation 'org.apache.commons:commons-numbers:1.0'
...
}
但在在Eclipse執行[Refresh Gradle Project]的時候沒有注意到Eclipse的Console出現下面訊息。
Could not resolve: org.apache.commons:commons-numbers:1.0
CONFIGURE SUCCESSFUL in 2s
也就是找不到依賴的jar檔,然後在Eclipse整個專案也沒任何錯誤提示,導致不論在JUnit 4執行掛有@RunWith(SpringRunner.class)
的測試類別的JUnit測試時出現下面錯誤。
java.lang.NoClassDefFoundError: org/junit/runner/manipulation/Filter
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:264)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.loadTestLoaderClass(RemoteTestRunner.java:380)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.createRawTestLoader(RemoteTestRunner.java:370)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.createLoader(RemoteTestRunner.java:365)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.defaultInit(RemoteTestRunner.java:309)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.init(RemoteTestRunner.java:224)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:208)
Caused by: java.lang.ClassNotFoundException: org.junit.runner.manipulation.Filter
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 8 more
或在JUnit 5執行掛有@ExtendWith(SpringExtension.class)
的測試類別的JUnit測試時出現下面錯誤。
java.lang.NoClassDefFoundError: org/junit/platform/commons/util/Preconditions
at org.junit.platform.launcher.core.LauncherFactory.create(LauncherFactory.java:83)
at org.junit.platform.launcher.core.LauncherFactory.create(LauncherFactory.java:67)
at org.eclipse.jdt.internal.junit5.runner.JUnit5TestLoader.(JUnit5TestLoader.java:34)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at java.lang.Class.newInstance(Class.java:442)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.createRawTestLoader(RemoteTestRunner.java:370)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.createLoader(RemoteTestRunner.java:365)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.defaultInit(RemoteTestRunner.java:309)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.init(RemoteTestRunner.java:224)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:208)
Caused by: java.lang.ClassNotFoundException: org.junit.platform.commons.util.Preconditions
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 13 more
而當我把該不存在的jar檔設定從build.gradle
移除並重新執行[Refresh Gradle Project]後就不會出現以上錯誤了,JUnit 4及JUnit 5都可以正常執行。
然後我又試了一下,故意引入另一個不存在的依賴,會引發相同的問題。
總之就是在Eclipse的Gradle專案引入依賴函式庫時,要確認引用的函式庫位置和版本是否正確,如果引用錯誤時只有在執行[Refresh Gradle Project]會在Eclipse的[Console]出現 Could not resolve: <group:module:version>
的提示,但在Eclipse的[Markers]卻不會出現錯誤提示,進一步造成JUnit執行出現如上的錯誤。
這問題搞了我幾乎3個小時才解決。原本一直以為是JUnit還是Gradle設定錯誤造成的。
沒有留言:
張貼留言