Kotlin Multiplatform Android/iOS: Testing

Kotlin Multiplatform Android/iOS: Testing

A how-to guide on writing tests within Kotlin Multiplatform.

Testing

Code quality is very important. Testing is a huge part of code quality. You want to ensure the code you write behaves as expected. It also needs to work under a variety of conditions.



I use the Given When Then approach to testing across all our Small, Medium and Large tests. It's a useful way of structuring tests. I also rely on mocking within my tests. I want to ensure the only thing I am testing is the class(es) I intended.

Kotlin Multiplatform

Testing within Kotlin Multiplatform is well supported and will feel very familiar.

implementation "org.jetbrains.kotlin:kotlin-test-common:$kotlin_version"

implementation "org.jetbrains.kotlin:kotlin-test-annotations-common:$kotlin_version"

Kotlin provides some common test dependencies to enable you to write multiplatform tests. Meaning you only have to write your tests once, rather than writing platform-specific tests.

Example

Consider this simple repository:

We have two methods, both providing a way of getting a User. One provides a suspend function and one provides a callback approach. The callback returns an IOResult, which encapsulates success and error states. My Android app will use the suspend function, and my iOS app will use the callback function. Suspend functions aren't yet supported on iOS.

So we want to be able to write 4 tests:

- remoteFailure__getUser__error
- remoteSuccess__getUser__success
- callback_remoteFailure__getUser__error
- callback_remoteSuccess__getUser__success

following the naming convention of given__when__then. These will encapsulate all the possible scenarios for these methods.

Mocking

We will need to be able to mock our UserRemote. Currently there is no framework available for mocking classes within both Android and iOS. Mockk is on its way to supporting JS and Native (iOS) but is not yet complete.

So, we must create our own mock manually. This approach might be somewhat familiar to iOS developers.

We create a class which implements the UserRemote interface. It provides the ability to define the getUser behaviour by providing a function var. So, within a test we can set whenGetUser and provide some behaviour.

Coroutines

implementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutines_version"

To test a suspend function we need to add the coroutines test dependency.

Adding this expect and actual utility makes it easy to run our common test suspend functions.

Callbacks

To be able to assert on our callback results we need to be able to mock them.

This mock captures the params which the callback gets invoked with.

Tests

Using these components, we are now able to write our tests.

To create a mock of User we can write a little extension method:

 

Summary

Kotlin Multiplatform common test code can be a little cumbersome to write. Especially for an Android developer who makes use of frameworks like Mockito. But the ability to test commonly is very powerful. It will reduce your overall testing workload.

Want more Kotlin?

Check out Alistair's other musings on all things Kotlin:

- Kotlin Multiplatform iOS: Certificate Pinning

- Kotlin Multiplatform Android/iOS: Coding and culture

- Kotlin Multiplatform Android/iOS: Project Structure Strategies

- Kotlin is here. So what?


Looking for something else?

Search over 400 blog posts from our team

Want to hear more?

Subscribe to our monthly digest of blogs to stay in the loop and come with us on our journey to make things better!