Version Matrix

zio-test-akka-http

CI Release Issues Snapshot
Build Status Release Artifacts Average time to resolve an issue Snapshot Artifacts

Akka-HTTP route TestKit for zio-test

libraryDependencies += "info.senia" %% "zio-test-akka-http" % "x.x.x"

Usage

The basic structure of a test built with the testkit is this (expression placeholder in all-caps):

assertM(REQUEST ~> ROUTE) {
  ASSERTIONS
}

See RouteDefaultRunnableSpec.scala for usage examples.

Imports

Import zio.test.akkahttp.assertions._ and provide RouteTestEnvironment to use this testkit:

import akka.http.scaladsl.server.Directives.complete
import akka.http.scaladsl.model.HttpResponse
import zio.test.Assertion._
import zio.test._
import zio.test.akkahttp.RouteTestEnvironment
import zio.test.akkahttp.assertions._

object MySpec extends DefaultRunnableSpec {
  def spec =
    suite("MySpec")(
      testM("my test") {
        assertM(Get() ~> complete(HttpResponse()))(
          handled(
            response(equalTo(HttpResponse()))
          )
        )
      }
    ).provideSomeLayerShared[Environment](RouteTestEnvironment.environment)
}

Alternatively you can use DefaultAkkaRunnableSpec without importing assertions._ and providing additional environment:

import akka.http.scaladsl.server.Directives.complete
import akka.http.scaladsl.model.HttpResponse
import zio.test.Assertion._
import zio.test._
import zio.test.akkahttp.DefaultAkkaRunnableSpec

object MySpec extends DefaultAkkaRunnableSpec {
  def spec =
    suite("MySpec")(
      testM("my test") {
        assertM(Get() ~> complete(HttpResponse()))(
          handled(
            response(equalTo(HttpResponse()))
          )
        )
      }
    )
}

Request creation

You can use HttpRequest or ZIO[R, E, HttpRequest] as request:

import akka.http.scaladsl.model.HttpResponse
import akka.http.scaladsl.server.Directives.complete
import zio.test.Assertion._
import zio.test._
import zio.test.akkahttp.assertions._

assertM(Get() ~> complete(HttpResponse()))(
  handled(
    response(equalTo(HttpResponse()))
  )
)

Available request builders: Get,Post,Put,Patch,Delete,Options,Head.

Request modification

You can use any function HttpRequest => HttpRequest to modify request.

There are several common request modifications provided: addHeader,mapHeaders,removeHeader,addCredentials:

assertM(Get() ~> addHeader("MyHeader", "value") ~> route)(???)

You can also add header with ~> method:

assertM(Get() ~> RawHeader("MyHeader", "value") ~> route)(???)

Assertions

There are several assertions available:

  • handled
  • response
  • responseEntity
  • chunks
  • entityAs
  • responseAs
  • contentType
  • mediaType
  • charset
  • headers
  • header
  • status
  • closingExtension
  • trailer
  • rejected
  • rejection
  • isWebSocketUpgrade

There should be an assertion for every inspector from original Akka-HTTP Route TestKit. If you can't find an assertion for existing inspector please open an issue.

Note that assertions are lazy on response fetching - you can use assertions for status code and headers even if route returns an infinite body:

Assertions are incompatible with assert - use assertM instead.

import akka.http.scaladsl.model.StatusCodes.OK
import akka.http.scaladsl.server.Directives.{complete, get, respondWithHeader}
import akka.http.scaladsl.model.{ContentTypes, HttpEntity, HttpResponse}
import akka.http.scaladsl.model.headers.RawHeader
import akka.http.scaladsl.server.Directives
import akka.stream.scaladsl.Source
import akka.util.ByteString
import zio.test.Assertion._
import zio.test._
import zio.test.akkahttp.RouteTestEnvironment
import zio.test.akkahttp.assertions._

val pinkHeader = RawHeader("Fancy", "pink")

val route = get {
  respondWithHeader(pinkHeader) {
    complete(HttpEntity(ContentTypes.`application/octet-stream`, Source.repeat(ByteString("abc"))))
  }
}

assertM(Get() ~> route)(
  handled(
    status(equalTo(OK)) &&
      header("Fancy", isSome(equalTo(pinkHeader))),
  ),
)