1. Overview

An extension function in Kotlin is simply a function that allows us to add new functionality to an existing class without modifying its source code. This is especially useful when we want to add methods or operations to classes that we don’t have direct control over, such as classes from external libraries or the standard library. Extension functions are defined outside the class they extend and are called regular methods.

In this tutorial, we’ll briefly review how to write Kotlin extension functions, and then we’ll learn a couple of ways to test them.

2. Defining an Extension Function

An extension function is declared by using the fun keyword followed by the name of the class we want to extend, a dot (.), and the name of the function we want to add.

Let’s write an extension function for the String class:

fun String.reverse(): String {
    return this.reversed()
}

Here, we’ve created a simple extension function for the String class that returns the characters of the String in reverse order.

3. Using JUnit to Test Extension Functions

Let’s learn how we can test our reverse() function using the JUnit library.

Our first step is to ensure that we have the necessary dependencies in our project before writing the test. To set up JUnit, we’ll need to include the dependency in our pom.xml:

<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-engine</artifactId>
    <version>5.9.2</version>
    <scope>test</scope>
</dependency>

Let’s take a look at what this particular test would look like:

@Test
fun testEmptyStringReverse() {
    val emptyString = ""
    assertEquals("", emptyString.reverse())
}

@Test
fun testSingleCharStringReverse() {
    val singleCharString = "a"
    assertEquals("a", singleCharString.reverse())
}

@Test
fun testMultiCharStringReverse() {
    val multiCharString = "Hello, World!"
    assertEquals("!dlroW ,olleH", multiCharString.reverse())
}

We have three test cases, each with an input string and an assertion using assertEquals() to compare the actual output of the reverse() function with the expected results. Our test cases cover scenarios such as an empty string, a single-character string, and a multi-character string, ensuring that the function behaves correctly in each case. If all assertions pass without errors, it confirms that our reverse() function operates as expected.

4. Using Spek to Test Extension Functions

Spek is a Kotlin-based testing framework for the JVM. We can easily add Spek to any project that is using the JUnit 5 runner with other tests we might have already.

Our first step is to add the Spek dependency to our Maven project.

<dependency>
    <groupId>org.spekframework.spek2</groupId>
    <artifactId>spek-dsl-jvm</artifactId>
    <version>2.0.14</version> 
    <scope>test</scope>
</dependency>

Let’s take a look at how we can test our reverse() extension function using the Spek framework:

class StringExtensionSpec : Spek({
    describe("String Extension Tests") {
        it("should reverse a string correctly") {
            val inputString = "Hello, World!"
            val result = inputString.reverse()
            assertEquals("!dlroW ,olleH", result)
        }
        it("should handle an empty string") {
            val inputString = ""
            val result = inputString.reverse()
            assertEquals("", result)
        }
        it("should handle a single character string") {
            val inputString = "a"
            val result = inputString.reverse()
            assertEquals("a", result)
        }
    }
})

Here, we’ve defined a Spek specification using the describe() block. Inside the specification, we use the it() blocks to describe individual test cases. Then, we arrange the input, call the extension function, and assert the results in each test case.

5. Conclusion

In this article, we’ve looked at what an extension function is and defined a simple example. Then, we discussed two methods we can use to test our extension functions using the JUnit and Spek libraries.

As always, the examples used are available over on GitHub.