0

Akka Http version: "10.0.11"

I have the following route to test:

private def getAll: Route = pathPrefix("_all") {
  get {
    complete((todoRegistryActor ? GetAllTodos).mapTo[Todos].map(todosToTodoDtos))
  }
}

And I have the following test:

class TodoRouteSpec extends WordSpec with Matchers
  with ScalatestRouteTest with RouteManager with BeforeAndAfterAll with TestKitBase with ImplicitSender {

  override implicit val system: ActorSystem = ActorSystem("TodoRouteSpec")
  override val executionContext: ExecutionContext = system.dispatcher

  private val todoRegistryProbe = TestProbe()
  override implicit val todoRegistryActor: ActorRef = todoRegistryProbe.ref

  override def afterAll {
    TestKit.shutdownActorSystem(system)
  }

  "The service" should {
    "return a list of todos for GET _all request" in {
      Get("/api/todo/_all").~>(todoRoute)(TildeArrow.injectIntoRoute).~>(check {
        //todoRegistryProbe.expectMsg(GetAllTodos)

        responseAs[TodosDto] shouldEqual TodosDto(Seq.empty)
        status should ===(StatusCodes.OK)
      })
    }
  }
}

When running the following test, I receive the error: An exception or error caused a run to abort: ActorRefFactory context must be defined java.lang.IllegalArgumentException: ActorRefFactory context must be defined

  1. I was looking what raised this error, but I can't find a solution. Does somebody know what raises this error?
  2. TildeArrow.injectIntoRoute has to be explicitly passed to get the test running. Found the solution here: How can I fix the missing implicit value for parameter ta: TildeArrow in a test spec. Maybe someone knows another solution?

Thanks in advance

Solution

class TodoRouteSpec extends WordSpec with Matchers with ScalatestRouteTest with TodoRoute {

  private lazy val routes = todoRoute
  private val todoRegistryProbe = TestProbe()
  todoRegistryProbe.setAutoPilot((sender: ActorRef, _: Any) => {
    sender ! Todos(Seq.empty)
    TestActor.KeepRunning
  })
  override implicit val todoRegistryActor: ActorRef = todoRegistryProbe.ref

  "TodoRoute" should {
    "return a list of todos for GET /todo/_all request" in {
      Get("/todo/_all").~>(routes)(TildeArrow.injectIntoRoute).~>(check {
        todoRegistryProbe.expectMsg(GetAllTodos)

        status should ===(StatusCodes.OK)
        contentType should ===(ContentTypes.`application/json`)
        entityAs[TodosDto] shouldEqual TodosDto(Seq.empty)
      })
    }
  }
}

1 Answers1

1

You don't need actor system to do route tests.

See example in the documentation.

class FullTestKitExampleSpec extends WordSpec with Matchers with ScalatestRouteTest {

  val smallRoute =
    get {
      path("ping") {
        complete("PONG!")
      }
    }

  "The service" should {

    "return a 'PONG!' response for GET requests to /ping" in {
      // tests:
      Get("/ping") ~> smallRoute ~> check {
        responseAs[String] shouldEqual "PONG!"
      }
    }
  }
}
  • If you service needs actor system you can use Akka TestKit as described in https://doc.akka.io/docs/akka/2.5/testing.html#asynchronous-testing-testkit – Dragisa Krsmanovic Feb 21 '18 at 23:42
  • Thanks for the comment. I indeed did not need the actorsystem. But I wanted to verify that the actor is called with the correct message. Therefore you can use the setAutoPilot of the TestProbe(). I will post my specific solution –  Feb 24 '18 at 16:40