使用Maven构建时解决NoClassDefFoundError

时间:2012-09-18 07:45:04

标签: java testing maven noclassdeffounderror classnotfoundexception

在使用Maven运行测试时遇到了由ClassNotFoundException引起的NoClassDefFoundError。未找到的类肯定存在于我的本地存储库中。

有问题的依赖关系如下所示:默认的作用域依赖项依赖于一个jar,其范围是标记为提供的,而类加载器找不到的文件位于该jar内。它编译好了,在运行应用程序时无法找到该文件。

我通过将“提供的jar”明确地添加到我的pom作为运行时范围的依赖项来修复错误,但我想了解最新情况。

1)如果我正在运行一些测试,那么dependency scope =是什么意思?我知道servlet容器可以有一些提供的jar,比如servlet-api.jar,但测试呢?这看起来像我们的pom中的错误,不是吗? 除了来自servlet-api.jar(以及similair web-server jars)之外我们应该使用“提供”范围吗?

2)我在寻找此问题的解决方案时尝试使用maven命令行参数-U。据我了解,它迫使Maven检查远程存储库,并在必要时从那里获取最新鲜的依赖项。 一个问题是:如果我没有指定这个命令,会发生什么?它总会从本地存储库中获取过时的依赖项?如果没有,那么为什么我需要这个命令?

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

2 个答案:

答案 0 :(得分:2)

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

`mvn <goal> -PTest`

有关信息,请参阅Introduction on profiles

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

3)mvn dependency:tree

答案 1 :(得分:1)

1)您可以使用“测试容器”(Jetty,Tomcat)运行测试,在这种情况下,如果范围有意义(例如,我在prod中使用tomcat,但是使用jetty进行单元测试,他们不要甚至没有提供相同版本的罐子。

2)Maven默认使用它在本地仓库中找到的罐子,而不是搜索更新的罐子,如果不是快照的话。 如果你提供自己的罐子,你应该总是增加版本,即使它有时很烦人。

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