Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Testing Servers

Ktor provides some support for testing your server applications in an efficient way. It hooks tests directly into the framework’s routing mechanism, avoiding the need to run the underlying server and make network calls to it. This allows the tests to run a lot faster.

Task 4.4

  1. Download ktor-testing.zip from the Topic 2 folder in Minerva and unzip it in your SoCS Linux filestore or on your own PC.

  2. Examine the contents of the directory that is created. This is a Gradle project for a simple ‘Hello World’ Ktor application. Take a look at the build.gradle.kts file. Notice the addition of three testing dependencies:

    testImplementation("io.ktor:ktor-server-test-host")
    testImplementation("io.kotest:kotest-assertions-core:5.9.1")
    testImplementation("io.kotest:kotest-runner-junit5:5.9.1")
    

    You’ve seen the two Kotest dependencies before. The other dependency extends Ktor with the testing support that we need.

  3. Run the application with

    ./gradlew run
    

    Visiting http://0.0.0.0:7070 should give you a “Hello World!” message in the browser window.

    Try visiting http://0.0.0.0:7070/hello/Kotlin and you should see a “Hello Kotlin!” message instead.

  4. Now run the tests:

    ./gradlew test
    

    A single test should run, and it should pass.

  5. Locate the file ApplicationTest.kt and examine it. Here’s the code for the single test:

    "Path / yields 'Hello World!' greeting" {
        testApplication {
            application { module() }
            val response = client.get("/")
            response.status shouldBe HttpStatusCode.OK
            response.headers["Content-Type"]?.shouldContain("text/plain")
            response.bodyAsText() shouldBe "Hello World!"
        }
    }
    

    This is similar to the Kotest examples you’ve seen earlier, but there are some important differences.

    • The body of the test is contained in a lambda expression which is passed to the testApplication() function.

    • The first thing in this lambda expression is some code to configure the application, invoking its top-level module() function. (Remember that this, in turn, may invoke other modules, such as configureRouting().)

    • The second thing in the lambda expression is some code to make a request. A GET request can be made by invoking the get() extension function of a special object named client. A POST request can be made by invoking the post() function. The request returns a response, and we can make assertions about the content of this response.

    • The assertions have a form that should now be familiar to you. In this example, you can see how we can check three features of the HTTP response: the status code, the Content-Type header, and the body.

      • Notice how we use the object HttpStatusCode.OK to represent a status of 200 OK. There are constants like this defined for all other HTTP status codes.

      • Notice the use of the safe call operator when checking for the Content-Type header. This is because response.headers stores headers in a map, and looking up values in a map can return null.

      • The body of the response needs to be converted explicitly into a string before we can check it, which is achieved using the bodyAsText() extension function.

  6. The application has two routes, but only one of them is currently tested. Add the missing test to ApplicationTest.kt. Rerun the tests and make sure that both pass.

  7. Add a third test to check that a request for http://0.0.0.0:7070/hello produces a 404 Not Found response.

    Hint

    You can use the constant HttpStatusCode.NotFound in your assertion.

Further Reading

For more on how to test your applications, see the Testing in Ktor Server page in the official Ktor documentation.

The approach outlined above is suitable for testing only the request-handling code of a Ktor server. If you want to test all layers of software running on the server side, you could use Ktor to create a separate client application that makes a network request to a running server. This application could then make assertions about the response that it receives.

For full end-to-end testing of web applications in a browser, you should investigate tools like Playwright. This may come in handy for your project in Semester 2.