TestProbe не получает сообщения от RouteSpec - PullRequest
0 голосов
/ 06 декабря 2018

У меня проблемы при попытке "издеваться" над актером за маршрутом.Я хочу иметь возможность переопределять и моделировать функциональность во время тестирования, и я думаю, что TestProbe является правильным способом решения этой проблемы.

Однако я не получил TestProbe для получения одного запроса.При использовании probe.expectMsg(request) проверка завершается неудачно с assertion failed: timeout (3 seconds) during expectMsg while waiting for GetCardRequest(12345).Удаление вызовов expectMsg и reply все равно приведет к сбою теста из-за Request was rejected в блоке check.Я ожидаю, что 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]
            })
        })
    }
}

1 Ответ

0 голосов
/ 06 декабря 2018

Ваши тесты работают, но это только доказывает, что тестовый зонд никогда не вызывается.

Проверьте этот тест, который проходит OK

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
  • Я удалил классы дел, чтобы иметь возможность запустить его
...