TestProbe 未收到来自 RouteSpec 的消息

TestProbe not receiving messages from RouteSpec

我在尝试 "mock" 找出路线后面的 Actor 时遇到问题。我希望能够在测试时覆盖和模拟功能,并且我认为 TestProbe 是解决此问题的正确方法。

但是,我还没有得到一个 TestProbe 来接收单个请求。使用 probe.expectMsg(request) 时,测试失败并显示 assertion failed: timeout (3 seconds) during expectMsg while waiting for GetCardRequest(12345)。删除 expectMsgreply 调用仍然会导致测试失败,因为 check 块中的 Request was rejected。我希望 val result = request ~> routes ~> runRoute 能够命中底层的 TestProbe。

我觉得我只是不理解一些简单的设置!提前感谢您的帮助!

class MyRoutesSpec 
  extends WordSpec 
  with Matchers 
  with ScalaFutures 
  with ScalatestRouteTest
  with MyRoutes {
  lazy val routes = MyRoutes

  val probe = new TestProbe(system)
  override val cardLookupActor = probe.ref

  //TODO figure out how to get TestProbe to actually work!!
  "My Routes" should {
    "be able to get a card from a request" in {
      val cardRequest = GetCardRequest("12345")
      val cardRequestEntity = Marshal(cardRequest).to[MessageEntity].futureValue // futureValue is from ScalaFutures
      val request = Post("/getcard").withEntity(cardRequestEntity)
      val cardResponse = ClientCard("Hello", "World")

      val result = request ~> routes ~> runRoute

      probe.expectMsg(cardRequest)
      probe.reply(cardResponse)

      check {
        status should ===(StatusCodes.Created)
        contentType should ===(ContentTypes.`application/json`)
        entityAs[String] should ===("""{"cardName":"Hello", "cardType":"World"}""")
      } (result)
    }
  }
}


trait MyRoutes extends JsonSupport {

  // we leave these abstract, since they will be provided by the App
  implicit def system: ActorSystem

  lazy val log = Logging(system, classOf[MyRoutes])

  // other dependencies that Routes use
  def cardLookupActor: ActorRef

  // Required by the `ask` (?) method below
  implicit lazy val timeout = Timeout(5.seconds) 

  lazy val myRoutes: Route =
    pathPrefix("getcard") {
      concat(
        path(Segment) { id =>
          concat(
            get {
              val cardFuture: Future[ClientCard] =
                (cardLookupActor ? GetCardRequest(id = id)).mapTo[ClientCard]
            })
        })
    }
}

您的测试有效,但它只是证明从未调用过测试探针。

检查这个测试是否通过

import akka.Done
import akka.actor.ActorRef
import akka.actor.ActorSystem
import akka.event.Logging
import akka.http.scaladsl.server._
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.testkit.ScalatestRouteTest
import akka.testkit.TestProbe
import akka.util.Timeout
import org.scalatest.Matchers
import org.scalatest.WordSpec
import org.scalatest.concurrent.ScalaFutures
import akka.pattern.ask

import concurrent.duration._

class MyRoutesSpec extends WordSpec with Matchers with ScalaFutures with ScalatestRouteTest with MyRoutes {

  val probe = new TestProbe(system)
  override val cardLookupActor = probe.ref

  //TODO figure out how to get TestProbe to actually work!!
  "My Routes" should {
    "be able to get a card from a request" in {
      val cardRequest = "12345"
      val request = Get("/getcard/sss").withEntity(cardRequest)
      val cardResponse = "HelloWorld"

      val result = request ~> myRoutes ~> runRoute

      probe.expectMsg(Done)
      probe.reply(cardResponse)

      check {
        status should ===(StatusCodes.OK)
        entityAs[String] should ===("""HelloWorld""")
      }(result)
    }
  }
}

trait MyRoutes {

  // we leave these abstract, since they will be provided by the App
  implicit def system: ActorSystem

  lazy val log = Logging(system, classOf[MyRoutes])

  // other dependencies that Routes use
  def cardLookupActor: ActorRef

  // Required by the `ask` (?) method below
  implicit lazy val timeout = Timeout(5.seconds)

  lazy val myRoutes: Route =
    pathPrefix("getcard") {
      path(Segment) { _ =>
        get {
          complete((cardLookupActor ? Done).mapTo[String])
        }
      }
    }
}

修复了什么

  • lazy val routes = MyRoutes 已删除
  • 您发送 Post 但路由需要 Get
  • 没有通过测试的段,即/getcard在pathPrefix("getcard") {path(Segment) {id => ???}}中不匹配。
  • 调用 request ~> myRoutes ~> runRoute 而不是 request ~> routes ~> runRoute
  • 我删除了案例 类 只是为了能够 运行 它