Reading Time: 2 minutes

We will learn how we able to testing 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 = RejectionHandler.newBuilder() .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))) } .result()

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.

The 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 the 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:

Matching expected rejections Using Route.seal()

Conclusion

So using these two ways, we can write our test cases for all kinds of rejection handling and do testing for rejection handling in akka-http that we may do in our code.