Writing a GraphQL DSL in Kotlin

Reading Time: 3 minutes

I’ve recently spent some time testing a GraphQL endpoint against a few queries. At the moment I’m keeping my queries as multi-line strings but I was wondering:

How hard would it be to build a GraphQL query DSL in Kotlin?

I thought this could be a good opportunity to become more familiar with Kotlin DSL capabilities.

Here’s what I’ve got so far.

query("theQuery") {
    "allUsers"("type" to "users", "limit" to 10) {
        select("address") {
            select("street"("postCode" to true))

The above snippet produces the following result:

query theQuery {
    allUsers(type: "users", limit: 10) {
        address {
            street(postCode: true)

The main challenges I have faced up to this point have been around supporting:

  • any string to be used as the root field of the query (e.g."allUsers")
  • nested selection of fields
  • a map-like syntax for field arguments (I’ve settled for the to method for now)

Any String is a Field

As you can see from the above example, it is possible to start the root field declaration using a string, followed by the fields selection:

"allUsers" {

I’ve achieved that thanks to the Invoke operator overloading support. Read on to find out how I have implemented it.

String.invoke to the rescue

The incredibly powerful extensions support helps me define my own implementation of invoke on a String.

operator fun String.invoke(block: Field.Builder.() -> Unit) =
    Field.Builder().apply {

This way, any String instance can be turned into a Field.Builder by passing a block to the invoke operator (). Additionally, Kotlin’s compact syntax, saves us from having to explicitly use the open and close parenthesis, making the result a little more readable.

Select-ing sub-fields

"allUsers" {

Inside the declared root field, a sequence of select instructions informs the current field builder about which sub-fields we are interested in. The way this is achieved is by letting the compiler know that we are in the context of a Field.Builder and that any method specified in the block has to be resolved against it. This is possible thanks to function literals with receiver.

Function literals with receiver

This is probably the most useful feature Kotlin has to offer when it comes to building DSLs.

operator fun String.invoke(block: Field.Builder.() -> Unit)

The block argument has been declared as Field.Builder.() -> Unit.
As we can see from the docs:

[…] Kotlin provides the ability to call an instance of a function type with receiver providing the receiver object.

Function literals with receiver – Kotlin reference

What this means is that I can invoke the block having the current Field.Builder instance as receiver resulting in the select invocations to be being resolved against it.

Field arguments

When it comes to specifying field arguments, I’ve had to settle for that not-so-pretty to syntax.

"type" to "users", "limit" to 10

I still think it’s a good compromise considering that Kotlin doesn’t offer much more when it comes to map-building syntax.

"allUsers"("type" to "users", "limit" to 10) {
    select("address") {
        select("street"("postCode" to true))

The to method that allows for that comes from the standard library.

public infix fun <A, B> A.to(that: B): Pair<A, B> = Pair(this, that)

Note that the infix keyword is what allows for the simplified notation receiver method argument.

Finally, a slightly more complicated definition of String.invoke accepts instances of Pair<String, T> allowing for the to syntax to be used when specifying field arguments. The explicit String type as the left type helps keeping it all a little more robust.

operator fun <T> String.invoke(vararg args: Pair<String, T>, block: (Field.Builder.() -> Unit)? = null): Field.Builder

Wrapping up

As you can see, I’m not a DSL expert (at all!) but this is a fun experiment to play with. You can follow my work at the graphql-forger repo. Please, feel free to contribute by opening issues or pull requests.

I hope you have enjoyed the post and learnt something new about Kotlin.

Testing LiveData on Android

Reading Time: 3 minutes

Testing LiveData represents an interesting challenge due to the peculiarities of its technology and the way it eases development for your Android app.

I’ve recently started to build an Android app to keep motivated on my journey to learn Kotlin. My most recent experience has been with Architecture Components and this brief blog post, in particular, will focus on unit testing your DAO when using LiveData.

What is LiveData?

LiveData is a lifecycle-aware, observable data holder that will help you react to changes in you data source. In my case, I’m using it in combination with Room to make sure my app reacts to the new data becoming available in my database.

Our simple DAO

For this blog post let’s just pretend we have a very simple DAO that looks like the following:

This is just a DAO that helps you fetch posts.

As you can see, the return type for the function is not just a plain List<Post> but it wraps it in a LiveData instance. This is great because we can get an instance of our list of posts once and then observe for changes and react to them.

Let’s test it

The Android Developer documentation has a neat example on how to unit test your DAO:

This pretty simple test has the aim of testing that the data is being exposed correctly and that, once the post is added to the database, it is reflected by the getAll() invocation.

Unfortunately, by the time we are asserting on it, the value of the LiveData instance will not be populated and will make our test fail. This is because LiveData uses a lifecycle-oriented asynchronous mechanism to populate the underlying data and expects an observer to be registered in order to inform about data changes.

Observe your data

LiveData offers a convenient observe method that allows for observing the data as it changes. We can use it to register an observer that will assert on the expected value.

The observe method has the following signature:

void observe(LifecycleOwner owner, Observer<T> observer)

It expects an observer instance and the owner for its life-cycle. In our case, we’re only interested in keeping the observer around just enough to be able to assert on the changed data. We don’t want the same assertion to be evaluated every time the data changes.

Own your lifecycle

What we can do, then, is build an observer instance that owns its own life-cycle. After handling the onChange event we will mark the observer life-cycle as destroyed and let the framework do the rest.

Let’s see what the observer code looks like:

This observer implementation accepts a lambda that will be executed as part of the onChange event. As soon as the handler is complete, its own lifecycle will proceed to mark itself as ON_DESTROY which will trigger the removal process from the LiveData instance.

We can then create an extension on LiveData to leverage this kind of observer:

fun <T> LiveData<T>.observeOnce(onChangeHandler: (T) -> Unit) { 
    val observer = OneTimeObserver(handler = onChangeHandler) 
    observe(observer, observer)

Let’s test it again

A couple of things to notice this time.

First of all, we’re taking advantage of an InstantTaskExecutorRule. This is a helpful utility rule that takes care of swapping the background asynchronous task executor with a synchronous one. This is vital to be able to deterministically test our code. (Check this out if you wanna know more about JUnit rules).

In addition to that, we’re now leveraging the LiveData extension that we have written to write our assertions:

postDao.getAll().observeOnce {
    assertEquals(0, it.size)

We have just asserted in a much more compact and expressive way by leaving all the details inside our observer implementation. We are now asserting on the LiveData instance in a deterministic way making this kind of tests easier to read and write.


I hope this post will help you write tests for your DAO more effectively. This is one of my earliest experiences with Kotlin and Android: please, feel free to comment with better approaches to solve this.

Follow me on Twitter for more!

Cover photo by Irvan Smith on Unsplash