Maven故障保护失败,并出现java.lang.NoClassDefFoundError [英] Maven Failsafe fails with java.lang.NoClassDefFoundError
问题描述
我已经开始一个新项目: PostfixSQLConfig .这是一个简单的Spring Boot应用程序,必须为4个简单的数据库表提供CRUD访问.我为第一个表编写了存储库,并为该存储库编写了一些基本的集成测试.由于此特定表不应提供更新功能,因此我将更新功能实现为:
I've started a new project: PostfixSQLConfig. It's a simple Spring Boot application that is essentialy supposed to provide CRUD access for 4 simple databse tables. I wrote the the repository for the first table and some basic integration tests for said repository. Since this particular table should not provide update functionality, I implemented update function as:
@Override
public void update(@NonNull Domain domain) throws NotUpdatableException {
throw new NotUpdatableException("Domain entities are read-only");
}
其中 NotUpdatableException
是我的自定义异常类.
where NotUpdatableException
is my custom exception class.
此代码的IT看起来像这样:
The IT for this code look like this:
@Test(expected = NotUpdatableException.class)
public void testUpdate() throws NotUpdatableException {
val domain = Domain.of("test");
domainRepository.update(domain);
}
如果从我的IDE(IntelliJ 2018.2 EAP)运行此测试,则可以通过,但运行 mvn verify
失败,并显示以下信息:
If run this test from my IDE (IntelliJ 2018.2 EAP) it passes fine, but running mvn verify
fails with:
java.lang.NoClassDefFoundError: com/github/forinil/psc/exception/NotUpdatableException
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Class.java:2701)
at java.lang.Class.privateGetMethodRecursive(Class.java:3048)
at java.lang.Class.getMethod0(Class.java:3018)
at java.lang.Class.getMethod(Class.java:1784)
at org.apache.maven.surefire.util.ReflectionUtils.tryGetMethod(ReflectionUtils.java:60)
at org.apache.maven.surefire.common.junit3.JUnit3TestChecker.isSuiteOnly(JUnit3TestChecker.java:65)
at org.apache.maven.surefire.common.junit3.JUnit3TestChecker.isValidJUnit3Test(JUnit3TestChecker.java:60)
at org.apache.maven.surefire.common.junit3.JUnit3TestChecker.accept(JUnit3TestChecker.java:55)
at org.apache.maven.surefire.common.junit4.JUnit4TestChecker.accept(JUnit4TestChecker.java:53)
at org.apache.maven.surefire.util.DefaultScanResult.applyFilter(DefaultScanResult.java:102)
at org.apache.maven.surefire.junit4.JUnit4Provider.scanClassPath(JUnit4Provider.java:309)
at org.apache.maven.surefire.junit4.JUnit4Provider.setTestsToRun(JUnit4Provider.java:189)
at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:132)
at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:379)
at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:340)
at org.apache.maven.surefire.booter.ForkedBooter.execute(ForkedBooter.java:125)
at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:413)
Caused by: java.lang.ClassNotFoundException:
com.github.forinil.psc.exception.NotUpdatableException
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:338)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 18 more
老实说,我不知道为什么...
And I have honestly no idea why...
有人遇到过这个问题吗?
Has someone ever encountered this problem?
推荐答案
我知道了,所以我在回答自己的问题,以防其他人遇到相同的问题.
I figured it out, so I'm answering my own quesiton in case someone else has the same problem.
事实证明,maven-failsafe-plugin不会将target/classes目录添加到类路径,而是将生成的jar添加到大多数情况下都可以正常工作.
It turns out that maven-failsafe-plugin does not add target/classes directory to the classpath, but rather the resulting jar, which works fine in most cases.
但是,关于Spring Boot,生成的jar包含Spring Boot自定义类加载器类,而不是target/classes目录的内容,这些内容已移动到目录BOOT-INF/classes中.由于maven-failsafe-plugin使用常规"类加载器,因此它仅加载Spring Boot类加载器类,因此首先会失败,因此预计将使用其中一个项目类.
When it comes to Spring Boot, however, the resulting jar contains Spring Boot custom classloader classes in place of contents of target/classes directory, which are moved to directory BOOT-INF/classes. Since maven-failsafe-plugin uses 'regular' classloader it only loads Spring Boot classloader classes, failing in the first place it is expected to use one of the project classes.
要在Spring Boot项目中运行IT测试,必须从依赖项中排除打包的jar,然后添加原始的,未修改的jar或target/classes目录,这就是我所做的.
To run IT tests in Spring Boot project, one has to exclude the packaged jar from dependencies and add either the original, unmodified jar or target/classes directory, which is what I did.
maven-failsafe-plugin和Spring Boot的正确配置是:
The correct configuration for maven-failsafe-plugin and Spring Boot is:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.21.0</version>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
<configuration>
<classpathDependencyExcludes>
<classpathDependencyExcludes>${groupId}:${artifactId}</classpathDependencyExcludes>
</classpathDependencyExcludes>
<additionalClasspathElements>
<additionalClasspathElement>${project.build.outputDirectory}</additionalClasspathElement>
</additionalClasspathElements>
</configuration>
</plugin>
这篇关于Maven故障保护失败,并出现java.lang.NoClassDefFoundError的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!