Testing Rejection Handling in Akka-Http

In my previous blog, I discussed how to handle rejections in Akka Http.
You may find it here. We left it on terms to explain the testing of it later. Keeping the promise 😉

In this blog, we will learn how to be able to write the test cases for rejection handling in Akka-Http.
We will be using Akka TestKit and Akka-Http TestKit.
Dependencies are as follows:

"com.typesafe.akka" %% "akka-testkit" % "2.4.16"
"com.typesafe.akka" %% "akka-http-testkit" % "10.0.1"

Suppose we have a rejection builder

implicit def rejectionHandler =
    .handle { case MissingQueryParamRejection(param) =>
      val errorResponse = write(ErrorResponse(BadRequest.intValue, "Missing Parameter", s"The required $param was not found."))
      complete(HttpResponse(BadRequest, entity = HttpEntity(ContentTypes.`application/json`, errorResponse)))

and a route

path("check") {
   get {
    parameters('color, 'bgColor) {
      (color, bgColor) =>
        val properResponse = write(ProperResponse(OK.intValue, s"Your preference is color $color with background color $bgColor."))
        complete(HttpResponse(OK, entity = HttpEntity(ContentTypes.`application/json`, properResponse)))

A regular test case for this route would look like

"return proper response for check route if all parameters are provided" in {
  Get("/check?color=red&bgColor=white") ~> webServer.route ~> check {
    responseAs[String] shouldEqual """{"code":200,"message":"Your preference is color red with background color white."}"""

But what if we want to test when the parameters are missing?

That test case will be

"return a missing query parameter rejection for check route when parameters are not supplied" in {
    Get("/check") ~> webServer.route ~> check {
      rejection shouldEqual MissingQueryParamRejection("color")

Because we are passing no parameter, the route will certainly throw a rejection. And hence, we match the rejection that the route will throw with expected rejection. In the above case, MissingQueryParamRejection also expects a parameter (which is the first parameter that is missing), hence we match our rejection against MissingQueryParamRejection("color").

But as you must have noticed, our rejection handler gives a properly formatted response.
Testing response is equally important. It cannot be done like this,

"return a formatted response when a parameter rejection is encountered on check route" in {
  Get("/check?color=red") ~> webServer.route ~> check {
    responseAs[String] shouldEqual """{"code":400,"type":"Missing Parameter","message":"The required bgColor was not found."}"""

There is, however, a mechanism provided by Akka Http to test that even.
We do this by wrapping our route in akka.http.scaladsl.server.Route.seal. This is only needed in our test cases and not in the main code(but ensure that rejection handler is implicitly available in main code).
For writing the test case, we do need to bring our rejection handler in the scope of the test code which will look something like

implicit def rejectionHandler = webServer.rejectionHandler

And then, the test code will be –

"return a formatted response when a parameter rejection is encountered on check route" in {
  Get("/check?color=red") ~> Route.seal(webServer.route) ~> check {
    responseAs[String] shouldEqual """{"code":400,"type":"Missing Parameter","message":"The required bgColor was not found."}"""

Notice how the route has been wrapped inside Route.seal(). Doing it this way, allows us to check whether our rejection handler send the response the way we expected or not.

So eventually we have two ways to test our rejections:

  1. Matching expected rejections
  2. Using Route.seal()

So using these two ways, we can write our test cases for all kind of rejection handling that we may do in our code. You may find the entire code  here.

Thank you for the read. Happy Coding 🙂


This entry was posted in Akka, akka-http, Scala, Test, testing, tests. Bookmark the permalink.

2 Responses to Testing Rejection Handling in Akka-Http

  1. Dario says:

    Thanks, that was helpful!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s