Search code examples
kotlinakkaakka-http

Using Akka Route TestKit with Kotlin Spek


I am trying to test my AkkaHTTP routes (written in Kotlin) using akka-http-testkit. The tests in our project use Spek and I would like to keep it this way.
The Route TestKit tutorial gives a Java example:

public class TestkitExampleTest extends JUnitRouteTest {
    TestRoute appRoute = testRoute(new MyAppService().createRoute())

    @Test
    public void testCalculatorAdd() {
        // test happy path
        appRoute.run(HttpRequest.GET("/calculator/add?x=4.2&y=2.3"))
            .assertStatusCode(200)
            .assertEntity("x + y = 6.5")

        // test responses to potential errors
        appRoute.run(HttpRequest.GET("/calculator/add?x=3.2"))
            .assertStatusCode(StatusCodes.NOT_FOUND) // 404
            .assertEntity("Request is missing required query parameter 'y'")

        // test responses to potential errors
        appRoute.run(HttpRequest.GET("/calculator/add?x=3.2&y=three"))
            .assertStatusCode(StatusCodes.BAD_REQUEST)
            .assertEntity("The query parameter 'y' was malformed:\n" +
                "'three' is not a valid 64-bit floating point value")
    }
}

The setup uses the testRoute function, which means the test class must extend JUnitRouteTest.

Attempting to translate to a Kotlin Spek test I got this:

class TestKitExampleTest : JUnitRouteTest(), Spek({

  describe("My routes") {
    val appRoute = testRoute(MyAppService().createRoute())

    it("calculator add") {
      // test happy path
      appRoute.run(HttpRequest.GET("/calculator/add?x=4.2&y=2.3"))
        .assertStatusCode(200)
        .assertEntity("x + y = 6.5")
      //...rest omitted
    }
  }
})

which does not compile as the class is attempting to inherit two classes. I converted it to the following instead:

class TestKitExampleTest : Spek({

  describe("My routes") {
    val appRoute = testRoute(MyAppService().createRoute())

    it("calculator add") {
      // test happy path
      appRoute.run(HttpRequest.GET("/calculator/add?x=4.2&y=2.3"))
        .assertStatusCode(200)
        .assertEntity("x + y = 6.5")
      //...rest omitted
    }
  }
}) {
  companion object : JUnitRouteTest()
}

which encouters the runtime error java.lang.IllegalStateException: Unknown factory null at akka.http.impl.util.package$.actorSystem(package.scala:34).

Is there a way to use Akka's route testkit with Spek? Or is there another way to test these routes?


Solution

  • As @raniejade mentioned above, answered on Github. JUnitRouteTest bootstraps Akka with a rule, but Spek's LifeCycleListener can do the same thing.

    Adding the code:

    class SpekRouteBootstrapper: LifecycleListener, JUnitRouteTest() {
      override fun beforeExecuteTest(test: TestScope) {
        systemResource().before()
      }
    
      override fun afterExecuteTest(test: TestScope) {
        systemResource().after()
      }
    } 
    

    allowed me to do this on the test class:

    class TestKitExampleTest: Spek({
      val bootstrapper = SpekRouteBootstrapper()
      registerListener(bootstrapper)
    
      describe("My routes") {
        val appRoute by memoized {
          bootstrapper.testRoute(MyAppService().createRoute())
        }
    
        it("calculator add") {
          // test happy path
          appRoute.run(HttpRequest.GET("/calculator/add?x=4.2&y=2.3"))
            .assertStatusCode(200)
            .assertEntity("x + y = 6.5")
        }
      }
    })