You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Scala Play单元测试中修改FakeApplication的JDBC URL?

解决Play框架测试中DB URL不兼容的问题

方案1:从配置文件读取DB参数(推荐)

硬编码DB URL会导致生产与测试环境参数不一致,建议从Play配置文件读取参数,实现环境隔离:

  1. 在application.conf添加生产环境DB配置:
db.readwrite {
  url = "jdbc:postgresql://db:5432/postgres"
  user = "你的用户名"
  password = "你的密码"
  driver = "org.postgresql.Driver"
}
  1. 在application.test.conf添加测试环境配置(覆盖生产URL):
include "application.conf"
db.readwrite.url = "jdbc:postgresql://localhost:5432/postgres"
  1. 修改DB配置类,注入Play的Configuration读取参数:
import play.api.Configuration
import com.zaxxer.hikari.HikariConfig

object DBConnectionConfig {
  def hikariConfig(config: Configuration): HikariConfig = {
    val dbConfig = config.get[Configuration]("db.readwrite")
    val hikariConfig = new HikariConfig
    hikariConfig.setDriverClassName(dbConfig.get[String]("driver"))
    hikariConfig.setJdbcUrl(dbConfig.get[String]("url"))
    hikariConfig.setUsername(dbConfig.get[String]("user"))
    hikariConfig.setPassword(dbConfig.get[String]("password"))
    hikariConfig
  }
}
  1. 更新Module,注入Configuration:
import com.google.inject.{Provides, Singleton}
import play.api.Configuration
import io.getquill.{PostgresJdbcContext, SnakeCase}
import java.time.Duration
import com.zaxxer.hikari.HikariDataSource

class ReadWriteDB extends ScalaModule {

  @Singleton
  @Provides
  @Named("db.sql.readwrite.quill.context")
  def quillContext(config: Configuration): PostgresJdbcContext[SnakeCase.type] = {
    val ds = new HikariDataSource(DBConnectionConfig.hikariConfig(config))
    QuillFactory.create(ds, Duration("2m"))
  }
}
  1. 测试中覆盖配置或指定测试配置文件:
import play.api.test._
import play.api.test.Helpers._

class HealthCheckSpec extends PlaySpec with GuiceOneAppPerTest with Injecting {

  // 方式A:直接覆盖配置参数
  override def fakeApplication(): Application = {
    GuiceApplicationBuilder()
      .configure(
        "db.readwrite.url" -> "jdbc:postgresql://localhost:5432/postgres"
      )
      .build()
  }

  // 方式B:加载测试专用配置文件
  // override def fakeApplication(): Application = {
  //   GuiceApplicationBuilder()
  //     .loadConfig(Configuration.load(play.api.Environment.simple(mode = Test)))
  //     .build()
  // }

  "HealthCheck status" should {
    "reply from the router" in {
      val request = FakeRequest(GET, "/status")
      val home = route(app, request).get

      status(home) mustBe OK
      contentAsString(home) must include("API is running!")
    }
  }
}

方案2:Mock DB依赖(单元测试最佳实践)

健康检查接口无需真实DB连接,可Mock掉QuillContext,避免依赖外部数据库:

import play.api.test._
import play.api.test.Helpers._
import com.google.inject.name.Names
import io.getquill.{PostgresJdbcContext, SnakeCase}
import org.scalamock.scalatest.MockFactory

class HealthCheckSpec extends PlaySpec with GuiceOneAppPerTest with Injecting with MockFactory {

  override def fakeApplication(): Application = {
    GuiceApplicationBuilder()
      // 替换真实QuillContext为Mock实例
      .overrides(bind[PostgresJdbcContext[SnakeCase.type]]
        .annotatedWith(Names.named("db.sql.readwrite.quill.context"))
        .toInstance(mock[PostgresJdbcContext[SnakeCase.type]]))
      .build()
  }

  "HealthCheck status" should {
    "reply from the router" in {
      val request = FakeRequest(GET, "/status")
      val home = route(app, request).get

      status(home) mustBe OK
      contentAsString(home) must include("API is running!")
    }
  }
}

方案3:临时修改硬编码(不推荐,仅调试用)

若仅临时调试,可通过反射修改硬编码URL,但该方式缺乏扩展性,不建议长期使用:

class HealthCheckSpec extends PlaySpec with GuiceOneAppPerTest with Injecting {

  override def beforeAll(): Unit = {
    super.beforeAll()
    // 反射修改DBConnectionConfig的硬编码URL
    val field = classOf[DBConnectionConfig.type].getDeclaredField("jdbcUrl")
    field.setAccessible(true)
    field.set(null, "jdbc:postgresql://localhost:5432/postgres")
  }

  "HealthCheck status" should {
    "reply from the router" in {
      val request = FakeRequest(GET, "/status")
      val home = route(app, request).get

      status(home) mustBe OK
      contentAsString(home) must include("API is running!")
    }
  }
}

内容的提问来源于stack exchange,提问作者Lossan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 14:15:31