我有一个中等规模的sbt项目(20个子项目,50个直接依赖项,400个传递依赖项).我正在准备这个项目,以便进行单元测试。我遇到了一些奇怪的问题,并注意到用于某些依赖项的确切版本在Compile和Test目标之间存在差异,即单元测试(sbt test)与项目直接(sbt run)不同版本的库一起运行。
我在sbt Compile/dependencyList 1和sbt Test/dependencyList的输出之间产生了差异,并看到了大约50个不同版本的依赖项。我知道我可以使用dependencyOverride设置,但是手动处理数百个依赖项似乎是不切实际的。每当我们想更新我们的直接依赖项时,我也必须更新这个列表。
处理这种情况的打算是什么?也就是说,如何确保在单元测试期间使用与在生产中运行时相同的依赖关系版本?
::迟到总比没有好!)
1:dependencyList是来自依赖关系图的命令。
发布于 2019-04-15 12:48:15
首先,考虑确认依赖地狱是否确实是问题的原因。我们可以这样做的一种方法是运行包含所有运行时依赖项的fat jar测试。
将sbt-assembly添加到插件中,然后定义以下自定义命令:
commands += Command.command("testWithFatJar") { state =>
"set assembly / test := {}" ::
"assembly" ::
"set Test / fullClasspath := Attributed.blank((assembly / assemblyOutputPath).value) :: (Test / fullClasspath).value.toList" ::
"test" :: state
}请注意我们如何首先组装胖罐子,然后将其添加到测试类路径中。
Test / fullClasspath := Attributed.blank((assembly / assemblyOutputPath).value) :: (Test / fullClasspath).value.toList使它处于第一位。这里我们利用JVM的类路径排序属性
指定多个类路径条目的顺序很重要。Java解释器将按照类路径变量中出现的顺序查找目录中的类
这意味着,如果类路径上有相同的类,那么将使用第一个类。
胖罐子的位置由assemblyOutputPath任务提供:
inspect assembly::assemblyOutputPath
[info] Task: java.io.File
[info] Description:
[info] output path of the fat jar现在,执行testWithFatJar应该运行以下测试类路径:
sbt:how-to-guarantee-same-library-versions-for-compile-and-test-configurations> show Test / fullClasspath
[info] * Attributed(/Users/mario_galic/code/stackoverflow/how-to-guarantee-same-library-versions-for-compile-and-test-configurations/target/scala-2.12/how-to-guarantee-same-library-versions-for-compile-and-test-configurations-assembly-0.1.0-SNAPSHOT.jar)
[info] * Attributed(/Users/mario_galic/code/stackoverflow/how-to-guarantee-same-library-versions-for-compile-and-test-configurations/target/scala-2.12/test-classes)
[info] * Attributed(/Users/mario_galic/code/stackoverflow/how-to-guarantee-same-library-versions-for-compile-and-test-configurations/target/scala-2.12/classes)
[info] * Attributed(/Users/mario_galic/.ivy2/cache/org.scala-lang/scala-library/jars/scala-library-2.12.8.jar)
[info] * Attributed(/Users/mario_galic/.ivy2/cache/org.scalatest/scalatest_2.12/bundles/scalatest_2.12-3.0.5.jar)
[info] * Attributed(/Users/mario_galic/.ivy2/cache/org.scalactic/scalactic_2.12/bundles/scalactic_2.12-3.0.5.jar)
[info] * Attributed(/Users/mario_galic/.ivy2/cache/org.scala-lang/scala-reflect/jars/scala-reflect-2.12.8.jar)
[info] * Attributed(/Users/mario_galic/.ivy2/cache/org.scala-lang.modules/scala-xml_2.12/bundles/scala-xml_2.12-1.0.6.jar)注意*-assembly-0.1.0-SNAPSHOT.jar在第一个位置上的位置。一旦我们确认依赖地狱是原因,那么我们就可以开始思考什么是永久构建修改才能解决这个问题。
发布于 2021-05-10 09:13:49
下面是我的脚本,它检测仅存在于生产配置中但不在测试配置中的依赖项(及其版本)。
它依赖于安装依赖图SBT插件。
我将它集成到我们的CI中,如果只检测到任何生产依赖项,它就会使构建失败。
#!/bin/bash
# http://redsymbol.net/articles/unofficial-bash-strict-mode/
set -euo pipefail
IFS=$'\n\t'
echo Getting dependencyList for production config
sbt "-Dsbt.log.noformat=true" dependencyList > dependency-list-production-raw.txt
echo Getting dependencyList for test config
sbt "-Dsbt.log.noformat=true" test:dependencyList > dependency-list-test-raw.txt
clean_up_dependency_list () {
# non GNU sed version (less readable IMHO)
# sed -n 's/[[:space:]]*\[info\][[:space:]]*\([^:]\{1,\}:[^:]\{1,\}:[^:]\{1,\}\)\s*$/\1/p' | sort | uniq
sed --regexp-extended -n 's/^\s*\[info\]\s*([^:]+:[^:]+:[^:]+)\s*$/\1/p' | sort | uniq
}
clean_up_dependency_list < dependency-list-production-raw.txt > dependency-list-production.txt
clean_up_dependency_list < dependency-list-test-raw.txt > dependency-list-test.txt
echo Dependencies in dependency-list-production.txt: "$(wc -l < dependency-list-production.txt)"
echo Dependencies in dependency-list-test.txt: "$(wc -l < dependency-list-test.txt)"
dependencies_only_in_prod=$(comm -23 dependency-list-production.txt dependency-list-test.txt)
if [ -n "$dependencies_only_in_prod" ]; then
cat <<EOF
ERROR: Dependencies that are _not present in test_
configuration detected!
This may signal a problem where a _different_ (older?) version of
a dependency will be used in production than what would be used in
production.
Offending dependencies that are present _only in prod_:
$dependencies_only_in_prod
Full list of dependencies in test:
$(cat dependency-list-test.txt)
List of dependencies in production:
$(cat dependency-list-production.txt)
EOF
exit 1
fihttps://stackoverflow.com/questions/55686652
复制相似问题