java.lang.NoClassDefFoundError 使用 REST-assured 3.0.0 和 Java 11(未观察到 Java 8)

java.lang.NoClassDefFoundError with REST-assured 3.0.0 and Java 11 (not observed with Java 8)

这是我的 build.gradle 文件的样子:

plugins {
    id 'java'
    id "com.github.lkishalmi.gatling" version "0.7.0"
    id 'application'
}

sourceCompatibility = 1.8

repositories {
    mavenCentral()
}

dependencies {
    compile group: 'io.rest-assured', name: 'rest-assured', version: '3.0.0'
}

task runTests(type: Test) {
    useTestNG() {
        useDefaultListeners = true
        suites 'src/test/testng.xml'
    }
}

这是我的 testng.xml 的样子:

<!DOCTYPE suite SYSTEM "http://beust.com/testng/testng-1.0.dtd" >
<suite name="my-test-suite">
    <test name="myTest">
        <classes>
            <class name="tests.SomeTests">
                <methods>
                    <include name="testVerifySomething"/>
                </methods>
            </class>
        </classes>
    </test>
</suite>

java.lang.NoClassDefFoundError 错误源自 SomeTests class 行中从另一个 class SomeUtils 调用静态方法的行另一个包 utils.

这是完整的跟踪:

java.lang.NoClassDefFoundError: javax.xml.bind.JAXBException
    at io.restassured.config.ObjectMapperConfig.<init>(ObjectMapperConfig.java:49)
    at io.restassured.config.RestAssuredConfig.<init>(RestAssuredConfig.java:41)
    at io.restassured.RestAssured.<clinit>(RestAssured.java:420)
    at utils.SomeUtils.createUser(SomeUtils.java:13)
    at tests.SomeTests.createUser(SomeTests.java:63)
    at tests.SomeTests.testCreateUsers(SomeTests.java:47)
    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.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:124)
    at org.testng.internal.Invoker.invokeMethod(Invoker.java:583)
    at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:719)
    at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:989)
    at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:125)
    at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:109)
    at org.testng.TestRunner.privateRun(TestRunner.java:648)
    at org.testng.TestRunner.run(TestRunner.java:505)
    at org.testng.SuiteRunner.runTest(SuiteRunner.java:455)
    at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:450)
    at org.testng.SuiteRunner.privateRun(SuiteRunner.java:415)
    at org.testng.SuiteRunner.run(SuiteRunner.java:364)
    at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
    at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:84)
    at org.testng.TestNG.runSuitesSequentially(TestNG.java:1208)
    at org.testng.TestNG.runSuitesLocally(TestNG.java:1137)
    at org.testng.TestNG.runSuites(TestNG.java:1049)
    at org.testng.TestNG.run(TestNG.java:1017)
    at org.gradle.api.internal.tasks.testing.testng.TestNGTestClassProcessor.runTests(TestNGTestClassProcessor.java:139)
    at org.gradle.api.internal.tasks.testing.testng.TestNGTestClassProcessor.stop(TestNGTestClassProcessor.java:89)
    at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:61)
    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.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
    at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
    at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:32)
    at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93)
    at com.sun.proxy.$Proxy2.stop(Unknown Source)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker.stop(TestWorker.java:131)
    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.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
    at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
    at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:155)
    at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:137)
    at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:404)
    at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
    at org.gradle.internal.concurrent.ManagedExecutorImpl.run(ManagedExecutorImpl.java:46)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
    at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55)
    at java.base/java.lang.Thread.run(Thread.java:825)
Caused by: java.lang.ClassNotFoundException: javax.xml.bind.JAXBException
    at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:768)
    at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:1052)
    ... 56 more

目录结构如下所示:

build.gradle
src
--test
----java
------tests
        SomeTests
------utils
        SomeUtils

到目前为止我尝试过的:

  1. 在我的 build.gradle.
  2. dependencies 部分添加 runtime files('src/test/java/utils')
  3. 在我的 build.gradle.
  4. dependencies 部分添加 compile files('src/test/java/utils')
  5. 在我的 build.gradle.
  6. dependencies 部分中添加 1 和 2

编辑: 经过一些尝试和错误后,似乎 Java 版本是这里的原因,因为问题出现在 Java 11 而不是with Java 8. 我在多台机器上验证了这种行为,只是为了确保我的机器上没有任何特定的东西。

你的代码文件的 "root",即本例中的测试文件应该是 src/test/java。因此,您可以尝试添加 compile files('src/test/java') to yourtestClasspath` 变量。

您没有具体说明哪个 class 没有找到! 完整的 stackstrace 会有所帮助。

然而,正如您提到的,它在 jdk8 上工作,这意味着您很可能 using/depending 在某些 class 上,这些 class 在 jdk9 之后被删除,例如 jaxb、javax 等

如果是这种情况,您有两种选择:

  • 运行 您的 app/test 使用以下 jvmopts 设置 --add-modules=java.xml.bind,java.activation 或创建 .jvmopts 项目根目录下的文件
  • 在缺少 class 的基础上在您的构建中添加显式依赖关系

查看完整的错误跟踪后,错误似乎源自 REST-assured 库的代码。将 io.rest-assured 依赖项从 3.0.0 升级到 4.0.0 有助于解决这个问题。

你可以换个放心依赖的版本试试。从 3.0.0 到 4.1.2

<dependency>
        <groupId>io.rest-assured</groupId>
        <artifactId>rest-assured</artifactId>
        <version>4.1.2</version>
</dependency>

会有帮助

这是因为类路径中缺少 JAXB 库(Java 用于 XML 绑定的体系结构)。 JAXB 包含在 Java SE 10 或更早版本中,但它已从 Java SE 从 Java 11 或更新版本中删除 – 移至 Jakarta EE 项目下的 Java EE。 这意味着如果您遇到 JAXBException 错误,很可能您正在为您的项目使用 Java 11 或更新版本。所以要修复这个错误,你必须选择:

  1. 使用旧的 Java 版本,例如 JDK 8、9 或 10,默认情况下仍包含 JAXB 库。或者:
  2. 在项目的 pom.xml 文件中指定一个附加依赖项,如下所示:
    <dependency>
        <groupId>javax.xml.bind</groupId>
        <artifactId>jaxb-api</artifactId>
        <version>2.3.0</version>
    </dependency>

如果你不使用 Maven https://mvnrepository.com/artifact/javax.xml.bind/jaxb-api/2.3.0