Tests Everywhere - Kotlin
Tags: test, kotlin, kotest, mockk
Published: 2023-11-23 00:12:28

{% github rogervinas/tests-everywhere no-readme %}

[Kotlin](https://kotlinlang.org/) testing [this simple Hello World](https://dev.to/rogervinas/tests-tests-everywhere-1b6h) with [Kotest](https://kotest.io) and [MockK](https://mockk.io/)

- [Show me the code](#show-me-the-code)
  - [Implementation](#implementation)
  - [Test](#test)
- [Run this project using 🐳 docker](https://github.com/rogervinas/tests-everywhere/tree/main/kotlin#run-this-project-using--docker)
- [Run this project locally](https://github.com/rogervinas/tests-everywhere/tree/main/kotlin#run-this-project-locally)

## Show me the code

### Implementation

1. Create `HelloMessage` class in [HelloMessage.kt](https://github.com/rogervinas/tests-everywhere/blob/main/kotlin/src/main/kotlin/org/hello/HelloMessage.kt):

```kotlin
class HelloMessage {
  val text: String = "Hello World!"
}
```

We can create it as a class as [MockK](https://mockk.io/) is able to mock final classes.

2. Same way create `HelloConsole` class in [HelloConsole.kt](https://github.com/rogervinas/tests-everywhere/blob/main/kotlin/src/main/kotlin/org/hello/HelloConsole.kt):

```kotlin
class HelloConsole {
  fun print(text: String) {
    println(text)
  }
}
```

3. Create `HelloApp` class in [HelloApp.kt](https://github.com/rogervinas/tests-everywhere/blob/main/kotlin/src/main/kotlin/org/hello/HelloApp.kt):

```kotlin
class HelloApp(private val message: HelloMessage, private val console: HelloConsole) {
  fun printHello() {
    console.print(message.text)
  }
}
```

4. Create main class in [Main.kt](https://github.com/rogervinas/tests-everywhere/blob/main/kotlin/src/main/kotlin/org/hello/Main.kt) that wraps it all together:

```kotlin
fun main() {
  val message = HelloMessage()
  val console = HelloConsole()
  val app = HelloApp(message, console)
  app.printHello()
}
```

### Test

Following [Kotest > Writing Tests](https://kotest.io/docs/framework/writing-tests.html) and [MockK > Class mock](https://mockk.io/#class-mock) guides ...

1. Test `HelloMessage` in [HelloMessageTest.kt](https://github.com/rogervinas/tests-everywhere/blob/main/kotlin/src/test/kotlin/org/hello/HelloMessageTest.kt):

```kotlin
class HelloMessageTest : DescribeSpec({

  describe("HelloMessage") {
    it("should return hello world") {
      val message = HelloMessage()
      message.text shouldBe "Hello World!"
    }
  }
})
```

2. Test `HelloApp` in [HelloAppTest.kt](https://github.com/rogervinas/tests-everywhere/blob/main/kotlin/src/test/kotlin/org/hello/HelloAppTest.kt):

```kotlin
class HelloAppTest : DescribeSpec({

  describe("HelloApp") {
    it("should print hello message") {
      val messageText = "Hello Test!"

      // 2.1 Create a mock of HelloMessage
      val message = mockk<HelloMessage>()
      // 2.2 Return "Hello Test!" whenever text is called
      every { message.text } returns (messageText)

      // 2.3 Create a mock of HelloConsole
      val console = mockk<HelloConsole>()
      // 2.4 Do nothing whenever print is called
      every { console.print(any()) } just Runs

      // 2.5 Create a HelloApp, the one we want to test, passing the mocks
      val app = HelloApp(message, console)
      // 2.6 Execute the method we want to test
      app.printHello()

      // 2.7 Verify HelloConsole mock print() method
      // has been called once with "Hello Test!"
      verify { console.print(messageText) }
    }
  }
})
```

3. Test output should look like:

```
> Task :test

org.hello.HelloAppTest > HelloApp > should print hello message PASSED

org.hello.HelloMessageTest > HelloMessage > should return hello world PASSED

BUILD SUCCESSFUL in 3s
```

Happy Testing! 💙