0

使用Maven运行测试时遇到由ClassNotFoundException引发的NoClassDefFoundError。没有找到的类肯定存在于我的本地存储库中。使用Maven构建时解决NoClassDefFoundError

有问题的依赖关系如下所示:默认的作用域依赖依赖于一个jar,该作用域被标记为提供的,而类加载器找不到的文件位于jar内。它编译好,通过该文件不能找到,而runnig应用程序。

我已经修正了错误,将“提供的jar”明确地添加到我的pom中作为运行时范围的依赖项,但我想了解发生了什么。

1)如果我正在运行某些测试,依赖范围=提供的含义是什么?我明白一个servlet容器可以有一些提供的jar,比如servlet-api.jar,但是测试呢?这在我们的pom中看起来像是一个错误,不是吗? 当我们应该使用“provided”作用域时,除了servlet-api.jar(和similair web-server jars)是否还有其他情况?

2)我试图使用maven命令行参数-U,同时寻找这个问题的解决方案。就我所知,它迫使Maven检查远程存储库,并在必要时从那里获取最新的依赖关系。 问题是:如果我没有指定这个命令,怎么回事?它会始终从本地存储库中获取过时的依赖关系?如果没有,那为什么我需要这个命令?

3)为了解决这样的问题,最好在编译代码时知道哪些jar是真正在类路径上的,哪些是在运行代码时存在的。 Maven有可能吗?

回答

2

1)总是表示不应该将依赖关系复制到构建的工件上。测试时声明为提供的某些依赖项不会运行,因为这些依赖项在运行时需要。例如,您可以通过创建自己的配置文件“测试”来解决此问题。因此,在您的“测试”配置文件中,将您的依赖项声明为默认范围,这将覆盖提供的范围。之后,您可以使用以下命令运行测试:

`mvn <goal> -PTest` 

有关信息,请参阅Introduction on profiles

2)据我所知,命令行参数-U会导致新获取依赖关系,因为您的存储库可能被破坏(例如,如果您更改或删除了那里的文件)。

3)mvn dependency:tree

1

1)您可以运行使用“测试容器”测试(码头,Tomcat)的,在这种情况下,提供范围是有道理的(例如,我在督促使用Tomcat,但用码头单元测试,他们甚至没有提供相同版本的罐子)。

2)默认情况下,Maven会将其在本地回购库中找到的罐子,不搜索更近的一个,如果不是快照。 如果你提供自己的罐子,你应该总是增加版本,即使它有时很烦人。

3)mvn依赖:树可以为您提供项目的所有依赖树。一些IDE(我使用eclipse)为您提供了一些不错的UI工具。