Unit Tests, Mock HTTP & UI Tests in Kotlin Compose Desktop | Lesson 15
Video: Unit Tests, Mock HTTP & UI Tests in Kotlin Compose Desktop | Lesson 15 by Taught by Celeste AI - AI Coding Coach
Watch full page →Unit Tests, Mock HTTP & UI Tests in Kotlin Compose Desktop
Testing Kotlin Compose Desktop applications involves combining unit tests, HTTP mocking, and UI tests for robust coverage. This example refactors a weather app to inject an HttpClient, enabling isolated tests of business logic and UI components using Ktor's MockEngine and Compose's testing APIs.
Code
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.*
import io.ktor.client.*
import io.ktor.client.engine.mock.*
import io.ktor.client.request.*
import io.ktor.client.statement.*
import io.ktor.http.*
import kotlinx.coroutines.runBlocking
import kotlinx.serialization.Serializable
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
import org.junit.Rule
import org.junit.Test
// Pure function mapping WMO weather codes to descriptions
fun weatherDescription(code: Int): String = when (code) {
0 -> "Clear"
1 -> "Partly Cloudy"
2 -> "Cloudy"
else -> "Unknown"
}
// Serializable data class for weather API response
@Serializable
data class WeatherResponse(val temperature: Double, val wmoCode: Int)
// Function to fetch weather using injected HttpClient
suspend fun fetchWeather(client: HttpClient): WeatherResponse {
val response: String = client.get("https://api.weather.com/current")
return Json.decodeFromString(response)
}
class WeatherTests {
@get:Rule
val composeTestRule = createComposeRule()
// Unit test for pure function
@Test
fun testWeatherDescription() {
assert(weatherDescription(0) == "Clear")
assert(weatherDescription(2) == "Cloudy")
assert(weatherDescription(99) == "Unknown")
}
// Test JSON deserialization
@Test
fun testDeserialization() {
val json = """{"temperature":22.5,"wmoCode":1}"""
val weather = Json.decodeFromString<WeatherResponse>(json)
assert(weather.temperature == 22.5)
assert(weather.wmoCode == 1)
}
// Mock HTTP client returning a fixed JSON response
private val mockClient = HttpClient(MockEngine) {
engine {
addHandler { request ->
respond(
content = """{"temperature":15.0,"wmoCode":0}""",
status = HttpStatusCode.OK,
headers = headersOf("Content-Type" to listOf(ContentType.Application.Json.toString()))
)
}
}
}
// Test fetchWeather with mocked HTTP client
@Test
fun testFetchWeather() = runBlocking {
val weather = fetchWeather(mockClient)
assert(weather.temperature == 15.0)
assert(weather.wmoCode == 0)
}
// Example Compose UI test using testTag and assertions
@Test
fun testWeatherScreenUI() {
composeTestRule.setContent {
// Compose UI showing weather description with test tag
androidx.compose.material.Text(
text = weatherDescription(1),
modifier = androidx.compose.ui.Modifier.testTag("weatherText")
)
}
// Assert UI text matches expected description
composeTestRule.onNodeWithTag("weatherText")
.assertExists()
.assertTextEquals("Partly Cloudy")
}
}
Key Points
- Injecting HttpClient enables mocking HTTP calls with Ktor's MockEngine for reliable tests.
- Pure functions like weatherDescription simplify unit testing by isolating logic from side effects.
- Use kotlinx.serialization to test JSON deserialization of API responses directly.
- Compose UI tests use createComposeRule, Modifier.testTag, and semantic queries for stable assertions.
- waitUntil and assertExists/assertTextEquals help verify asynchronous UI updates and error states.