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

如何使用ScalaTest和Akka HTTP测试路由中的连接失败场景?

没问题,我来一步步拆解怎么用ScalaTest + Akka HTTP测试你这个路由的数据库连接失败场景。核心思路是模拟数据库操作抛出异常,然后验证路由的错误处理逻辑是否符合预期。

首先,你需要先完善路由里的异常处理分支——你原来的代码里case F...没写完,得补上数据库连接失败时的处理,比如:

case Failure(_) => complete(StatusCodes.InternalServerError -> "connectionFail")

接下来,我们用ScalaTest + Akka HTTP TestKit + Mockito(用来模拟数据库层)来写测试:

1. 准备测试基础类

先搭建测试的骨架,引入必要的依赖并初始化测试路由和模拟的数据库实例:

import org.scalatest.BeforeAndAfterEach
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AnyWordSpec
import akka.http.scaladsl.testkit.ScalatestRouteTest
import akka.http.scaladsl.model._
import java.util.UUID
import org.mockito.Mockito._
import org.mockito.ArgumentMatchers._
import scala.concurrent.Future

// 假设你的路由依赖的Database定义和RuleRow实体是这样的(根据你的实际代码调整)
trait Database {
  def findById(id: UUID): Future[Option[RuleRow]]
  def update(row: RuleRow): Future[Int]
}
case class RuleRow(id: UUID, test: Boolean)

class RulesRouteSpec extends AnyWordSpec with Matchers with ScalatestRouteTest with BeforeAndAfterEach {
  // 模拟数据库实例
  private val mockDatabase = mock[Database]
  // 初始化测试用的路由(假设你的路由类通过构造注入接收Database)
  private val testRoute = new YourRulesRouteClass(mockDatabase).route

  // 每次测试前重置mock,避免测试间状态污染
  override def beforeEach(): Unit = {
    reset(mockDatabase)
  }

2. 测试「查找数据时数据库连接失败」场景

这个场景对应findById抛出异常的情况,我们要验证路由返回500错误和对应提示:

"PUT /rules/{id}" should {
    "return 500 Internal Server Error when database connection fails during lookup" in {
      val testId = UUID.randomUUID()
      // 模拟findById方法抛出连接失败的异常
      when(mockDatabase.findById(eqTo(testId)))
        .thenReturn(Future.failed(new RuntimeException("Database connection timed out")))

      // 发送PUT请求并验证响应
      Put(s"/rules/$testId") ~> testRoute ~> check {
        status shouldBe StatusCodes.InternalServerError
        responseAs[String] shouldBe "connectionFail"
      }
    }

3. 测试「更新数据时数据库连接失败」场景

这个场景是findById成功找到数据,但update时连接失败,验证路由的recover分支是否生效:

"return 500 Internal Server Error when database connection fails during update" in {
      val testId = UUID.randomUUID()
      val existingRow = RuleRow(testId, test = false)
      
      // 先模拟findById成功返回数据
      when(mockDatabase.findById(eqTo(testId)))
        .thenReturn(Future.successful(Some(existingRow)))
      // 再模拟update方法抛出连接异常
      when(mockDatabase.update(eqTo(existingRow.copy(test = true))))
        .thenReturn(Future.failed(new RuntimeException("Database connection lost during update")))

      Put(s"/rules/$testId") ~> testRoute ~> check {
        status shouldBe StatusCodes.InternalServerError
        responseAs[String] shouldBe "updateFail"
      }
    }
  }
}

关键注意点

  • 一定要用模拟的Database实例,不要连接真实数据库——我们要测试的是路由的错误处理逻辑,而非数据库本身。
  • 用Mockito的thenReturn(Future.failed(...))来模拟异步操作失败,这样路由里的onComplete会进入Failure分支。
  • Akka HTTP TestKit的~>操作符是测试路由的核心:发送请求 → 经过路由 → 检查响应。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 07:43:08