运行集成测试时,SBT 无法正确处理多模块项目中的资源。为什么?



>我在 sbt 项目上有以下配置:

  • moduleA包含一堆集成测试。
  • moduleB(取决于moduleA(。包含一个reference.conf文件;
  • moduleC(聚合moduleAmoduleB- 这是根(。

当我尝试运行it:test时出现错误,因为测试找不到reference.conf上可用的值。手动将reference.conf复制到moduleA即可使其正常工作。

问题似乎很明显,由于某种原因,在运行it:tests(在根目录(时,sbt 不够聪明,无法将reference.conf添加到类路径中。

谁能从理论上讲为什么会这样?sbt 如何与类路径和类装入器配合使用?它会将所有内容转储到单个类加载器中吗?情况似乎并非如此。

谢谢

为了解决您的问题和评论,让我分解一下SBT对您的项目所做的工作。

ModuleC项目,它聚合ModuleAModuleB。在SBT上下文中,聚合意味着在根项目上运行的任何命令也在聚合的子项目上运行。因此,例如,如果在根模块上运行集成测试,则还将对其聚合模块运行集成测试。但是,重要的是要了解这不是一次性完成的:该命令在每个子项目上单独运行。

SBT必须解决的下一个问题是处理子项目的顺序。在这种情况下,由于ModuleB取决于ModuleA,因此它必须在处理ModuleB之前处理ModuleA。否则,如果它们之间没有依赖关系,那么顺序就无关紧要了,SBT很可能会坚持它们在ModuleC聚合列表中指定的顺序。

但是,一个子项目依赖于另一个子项目意味着什么?这类似于SBT项目与其libraryDependencies之一之间的关系:依赖库必须可供子项目使用,并且其资源和类在指定的阶段(编译、测试、运行等(在类路径上可用。

所以,当集成测试在ModuleC上运行时,SBT将首先运行ModuleA的集成测试。由于ModuleA在项目中没有其他依赖项,因此将在其类路径上没有任何其他子项目的情况下对其进行处理。(这就是为什么它无法访问作为ModuleB一部分的reference.conf文件的原因。如果你考虑一下,这是有道理的,因为否则——如果ModuleAModuleB相互依赖——你将面临一个无法解决的先有鸡还是先有蛋的情况,在这种局面下,两个项目都无法构建。

(顺便说一句,如果ModuleA有尚未编译的源代码,那么在运行集成测试之前,它们将在单独的编译过程中进行编译。

接下来它将尝试处理ModuleB,将ModuleA的资源和类添加到它的类路径中,因为它依赖于它们。

从您的描述来看,似乎至少有一些ModuleBreference.conf文件中的配置设置应该属于ModuleA,因为它在集成测试期间需要访问它们。这是否意味着整个文件应该属于ModuleA取决于您。但是,每个子项目都可以有自己的reference.conf文件资源(这是我假设您正在使用的Typesafe Config库的设计功能(。任何属于ModuleAreference.conf文件的配置设置也可供ModuleB使用,因为它依赖于ModuleA。(如果您有多个reference.conf文件,您遇到的唯一问题将取决于您如何打包和发布ModuleC。例如,如果将所有子项目中的所有内容打包到单个JAR文件中,则需要将各种reference.conf文件合并在一起。

另一种可能性是,部分或全部集成测试实际上应该属于ModuleC,而不是ModuleAModuleB。同样,做出此决定将取决于您的要求。如果每个子项目在所有情况下都执行集成测试是有意义的,则将它们放在子项目中。如果它们只对整个已完成的项目有意义,那么将它们放在ModuleC.

有关更多详细信息,您可能需要阅读SBT 多项目构建的文档。

最新更新