简体   繁体   English

在运行集成测试时,sbt不能正确处理多模块项目中的资源。 为什么?

[英]sbt doesn't correctly deal with resources in multi-module projects when running integration tests. Why?

I have the following configuration on an sbt project: 我在sbt项目上具有以下配置:

  • moduleA Contains a bunch of integration tests. moduleA包含许多集成测试。
  • moduleB (depends on moduleA ). moduleB (取决于moduleA )。 Contains a reference.conf file; 包含一个reference.conf文件;
  • moduleC (aggregates moduleA and moduleB -- this is the root). moduleC (聚合moduleAmoduleB这是根)。

When I try to run it:test I get errors, as the tests cannot find the values available on reference.conf . 当我尝试运行it:test我得到了错误,因为测试找不到在reference.conf可用的值。 Manually copying the reference.conf to moduleA makes it work. 手动将reference.conf复制到moduleA使其起作用。

The issue seems clearly to be that by some reason when running the it:tests (at the root), sbt is not smart enough to add the reference.conf to the classpath. 问题似乎很明显是由于某种原因(在根目录下)运行it:tests时,sbt不够聪明,无法将reference.conf添加到类路径中。

Can anyone theorize why is that the case? 谁能推理出为什么会这样? How does sbt work with classpaths and classloaders? sbt如何与类路径和类加载器一起工作? Will it just dump everything in a single classloader? 它将仅将所有内容转储到单个类加载器中吗? It certainly doesn't seem to be the case. 似乎并非如此。

Thanks 谢谢

In order to address your question and comment, let me break down what SBT is doing with your project. 为了解决您的问题和评论,让我分解一下SBT对您的项目所做的事情。

ModuleC is the root project, and it aggregates ModuleA and ModuleB . ModuleC项目,它聚合 ModuleAModuleB In the context of SBT , aggregation means that any command that is run on the root project is also run on the aggregated sub-projects. SBT的上下文中, 聚合意味着在根项目上运行的任何命令也将在聚合的子项目上运行。 So, for example, if you run integration tests on the root module, then you will also run the integration tests for its aggregated modules. 因此,例如,如果您在根模块上运行集成测试,那么您还将为其聚合模块运行集成测试。 However, it's important to understand that this is not done all-at-once : the command is run on each sub-project individually. 但是,重要的是要了解这并非一次完成 :该命令在每个子项目上单独运行。

The next question that SBT has to address is the order in which the sub-projects should be processed. SBT必须解决的下一个问题是子项目的处理顺序。 In this case, since ModuleB depends on ModuleA , it has to process ModuleA before processing ModuleB . 在这种情况下,由于ModuleB 依赖 ModuleA ,因此它必须在处理ModuleA之前先处理ModuleB Otherwise, if there was no dependency between them, then the order wouldn't matter, and SBT would most likely stick with the order that they were specified in ModuleC 's aggregation list. 否则,如果它们之间没有依赖关系,则顺序将无关紧要, SBT很有可能会ModuleCModuleC的聚合列表中指定的顺序。

But what does it mean for one sub-project to depend upon another? 但是,一个子项目依赖另一个项目意味着什么? It's akin to the relationship between an SBT project and one of its libraryDependencies : the dependent library must be available to the sub-project, and its resources and classes are made available on the classpath during the indicated phases (compile, test, run, etc.). 这是类似于一个SBT项目和它的一个关系libraryDependencies :因库必须提供给子项目,它的资源和类中指定的阶段(编译,测试,运行等提供的类路径)。

So, when integration tests are run on ModuleC , SBT will first run ModuleA 's integration tests. 因此,当在ModuleC上运行集成测试时, SBT将首先运行ModuleA的集成测试。 Since ModuleA has no other dependencies within the project, it will be processed without any of the other sub-projects available on its classpath . 由于ModuleA在项目中没有其他依赖项,因此将对其进行处理, 而其classpath上没有任何其他子项目 (This is why it cannot access the reference.conf file that is part of ModuleB .) This makes sense, if you think about it, because otherwise—if ModuleA and ModuleB are dependent upon each other—you would have an unresolvable chicken-and-egg situation, in which neither project could be built. (这就是为什么它不能访问ModuleB一部分的reference.conf文件的原因。)如果考虑一下,这是有道理的,因为否则,如果ModuleAModuleB相互依赖,那么您将无法解决- -egg情况,无法建立任何项目。

(BTW, if ModuleA has sources that have not yet been compiled, then they will be compiled, on a separate compile pass, before running the integration tests.) (顺便说一句,如果ModuleA源代码尚未编译,则将在运行集成测试之前通过单独的编译过程对其进行编译。)

Next it will try to process ModuleB , adding ModuleA 's resources and classes to its classpath, since it is dependent upon them. 接下来,它将尝试处理ModuleB ,将ModuleA的资源和类添加到其类路径中,因为它依赖于它们。

From your description, it seems that at least some of the configuration settings in ModuleB 's reference.conf file should belong to ModuleA , since it needs access to them during its integration tests. 从您的描述看来, ModuleBreference.conf文件中的至少某些配置设置应该属于ModuleA ,因为它需要在集成测试期间访问它们。 Whether this means that the whole of the file should belong to ModuleA is up to you. 这是否意味着整个文件应属于ModuleA取决于您。 However, it's possible for each sub-project to have its own reference.conf file resource (that's a design feature of the Typesafe Config library that I'm assuming you're using). 但是,每个子项目都有可能拥有自己的reference.conf文件资源(这是我假设您正在使用的Typesafe Config库的设计功能)。 Any configuration settings that belong to ModuleA 's reference.conf file will also be available to ModuleB , since it is dependent upon ModuleA . 属于ModuleAreference.conf文件的任何配置设置也将可供ModuleB ,因为它取决于ModuleA (If you have multiple reference.conf files, the only issue you have will depend upon how you package and release ModuleC . If you package everything in all of your sub-projects into a single JAR file, then you would need to merge the various reference.conf files together, for example.) (如果您有多个reference.conf文件,则唯一的问题取决于打包和释放ModuleC 。如果将所有子项目中的所有内容打包到一个JAR文件中,则需要合并各种例如,将reference.conf文件放在一起。)

Another possibility is that some or all of the integration tests should actually belong to ModuleC rather than either ModuleA or ModuleB . 另一种可能性是,某些或所有集成测试实际上应该属于ModuleC而不是ModuleAModuleB Again, making this determination will depend upon your requirements. 同样,做出此决定将取决于您的要求。 If it makes sense for each sub-project to perform integration tests in all cases, then place them in the sub-projects. 如果每个子项目在所有情况下都执行集成测试是有意义的,则将它们放在子项目中。 If they only make sense for the completed project as a whole, then put them in ModuleC . 如果它们仅对整个已完成的项目有意义,则将它们放在ModuleC

You might want to read the documentation for SBT multi-project builds for further details. 您可能需要阅读SBT多项目构建的文档,以获取更多详细信息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM