如何在sbt项目中发布仅可供下游测试使用的对象
解决方案
原有方案的问题与修复(如果不拆分模块可以用这个方案)
你原来的配置无法找到MockData的核心原因是测试构件的依赖声明缺少classifier标识:
- sbt发布的测试Jar默认会带上
testsclassifier,你在引用方的依赖声明里没有指定该标识,因此无法加载对应构件 - 若要继续使用原有单模块方案,将引用方的依赖修改为:
ThisBuild / libraryDependencies ++= Seq( "org.my" %% "common" % "0.0.1", "org.my" %% "common" % "0.0.1" % Test classifier "tests" )
- 该方案缺点:会将common模块内部所有测试代码全部对外暴露,冗余度高,也容易泄露仅内部使用的测试逻辑,不推荐生产级公共类库使用。
拆分testkit独立模块方案(推荐)
你后续选择的拆分独立testkit模块是Scala生态公共类库的通用最佳实践,配置方式如下:
公共类库侧build.sbt配置
在根目录的build.sbt中声明两个子模块:
// 核心业务模块 lazy val common = (project in file("common")) .settings( name := "common", organization := "org.my", version := "0.0.1", scalaVersion := "2.13.8", // 替换为你的实际Scala版本 publishArtifact := true // 其他核心模块的依赖、自定义配置 ) // 测试工具包模块,仅对外提供测试所需的mock、工具类等 lazy val `common-testkit` = (project in file("common-testkit")) .settings( name := "common-testkit", organization := "org.my", version := "0.0.1", scalaVersion := "2.13.8", // 和核心模块保持一致 // 依赖核心模块的主代码,保证Mock可以用到核心模块定义的类 libraryDependencies += "org.my" %% "common" % version.value, publishArtifact := true // 其他testkit所需依赖,比如scalatest、mockito等测试框架依赖 )
执行sbt publishLocal即可同时将两个模块发布到本地仓库。
引用方项目配置
直接将testkit作为测试依赖引入即可:
ThisBuild / libraryDependencies ++= Seq( "org.my" %% "common" % "0.0.1", // 生产环境依赖核心模块 "org.my" %% "common-testkit" % "0.0.1" % Test // 仅测试环境依赖testkit )
该方案优势:
- 严格隔离生产代码和测试工具代码,生产环境不会引入任何测试相关依赖
- 可以单独维护testkit的对外API,灵活新增测试工具、Mock数据,不会和核心模块的内部测试代码混淆
- 符合Scala生态规范,Akka、Play等官方类库都采用该模式对外提供测试工具包
内容的提问来源于stack exchange,提问作者yuez
相关产品推荐
相关产品推荐

