From b4ba582ff03898c3cc1e5c4f415cb44acf3de66d Mon Sep 17 00:00:00 2001 From: James Rich <2199651+jamesarich@users.noreply.github.com> Date: Wed, 18 Mar 2026 15:39:34 -0500 Subject: [PATCH] feat(test): Integrate Mokkery, Turbine, and Kotest into KMP build logic --- build-logic/convention/build.gradle.kts | 1 + .../main/kotlin/KmpLibraryConventionPlugin.kt | 1 + .../meshtastic/buildlogic/KotlinAndroid.kt | 12 +++++ .../core/common/MokkeryIntegrationTest.kt | 47 +++++++++++++++++++ gradle/libs.versions.toml | 11 ++++- 5 files changed, 70 insertions(+), 2 deletions(-) create mode 100644 core/common/src/commonTest/kotlin/org/meshtastic/core/common/MokkeryIntegrationTest.kt diff --git a/build-logic/convention/build.gradle.kts b/build-logic/convention/build.gradle.kts index 31ae5278f..f3ecc5591 100644 --- a/build-logic/convention/build.gradle.kts +++ b/build-logic/convention/build.gradle.kts @@ -54,6 +54,7 @@ dependencies { compileOnly(libs.google.services.gradlePlugin) compileOnly(libs.koin.gradlePlugin) implementation(libs.kover.gradlePlugin) + implementation(libs.mokkery.gradlePlugin) compileOnly(libs.kotlin.gradlePlugin) compileOnly(libs.ksp.gradlePlugin) compileOnly(libs.androidx.room.gradlePlugin) diff --git a/build-logic/convention/src/main/kotlin/KmpLibraryConventionPlugin.kt b/build-logic/convention/src/main/kotlin/KmpLibraryConventionPlugin.kt index 36994fe26..214e0d8c4 100644 --- a/build-logic/convention/src/main/kotlin/KmpLibraryConventionPlugin.kt +++ b/build-logic/convention/src/main/kotlin/KmpLibraryConventionPlugin.kt @@ -34,6 +34,7 @@ class KmpLibraryConventionPlugin : Plugin { apply(plugin = "meshtastic.spotless") apply(plugin = "meshtastic.dokka") apply(plugin = "meshtastic.kover") + apply(plugin = libs.plugin("mokkery").get().pluginId) configureKotlinMultiplatform() configureKmpTestDependencies() diff --git a/build-logic/convention/src/main/kotlin/org/meshtastic/buildlogic/KotlinAndroid.kt b/build-logic/convention/src/main/kotlin/org/meshtastic/buildlogic/KotlinAndroid.kt index 4ec5d19b5..9107282af 100644 --- a/build-logic/convention/src/main/kotlin/org/meshtastic/buildlogic/KotlinAndroid.kt +++ b/build-logic/convention/src/main/kotlin/org/meshtastic/buildlogic/KotlinAndroid.kt @@ -114,12 +114,24 @@ internal fun Project.configureKmpTestDependencies() { val commonTest = findByName("commonTest") ?: return@apply commonTest.dependencies { implementation(kotlin("test")) + implementation(libs.library("kotest-assertions")) + implementation(libs.library("kotest-property")) + implementation(libs.library("turbine")) } // Configure androidHostTest if it exists val androidHostTest = findByName("androidHostTest") androidHostTest?.dependencies { implementation(kotlin("test")) + implementation(libs.library("kotest-assertions")) + implementation(libs.library("kotest-property")) + implementation(libs.library("turbine")) + } + + // Configure jvmTest if it exists + val jvmTest = findByName("jvmTest") + jvmTest?.dependencies { + implementation(libs.library("kotest-runner-junit6")) } } } diff --git a/core/common/src/commonTest/kotlin/org/meshtastic/core/common/MokkeryIntegrationTest.kt b/core/common/src/commonTest/kotlin/org/meshtastic/core/common/MokkeryIntegrationTest.kt new file mode 100644 index 000000000..c04c44f7f --- /dev/null +++ b/core/common/src/commonTest/kotlin/org/meshtastic/core/common/MokkeryIntegrationTest.kt @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2026 Meshtastic LLC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.meshtastic.core.common + +import dev.mokkery.answering.returns +import dev.mokkery.every +import dev.mokkery.mock +import dev.mokkery.verify +import io.kotest.matchers.shouldBe +import kotlin.test.Test + +interface SimpleInterface { + fun doSomething(input: String): Int +} + +class MokkeryIntegrationTest { + + @Test + fun testMokkeryAndKotestIntegration() { + val mock = mock() + + every { mock.doSomething("hello") } returns 42 + + val result = mock.doSomething("hello") + + result shouldBe 42 + + verify { + mock.doSomething("hello") + } + } +} diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index fc11b2d2c..b27f55e9f 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -26,7 +26,8 @@ kotlinx-datetime = "0.7.1-0.6.x-compat" kotlinx-serialization = "1.10.0" ktlint = "1.7.1" kover = "0.9.7" -mockk = "1.14.9" +mokkery = "3.3.0" +kotest = "6.1.7" testRetry = "1.6.4" turbine = "1.2.1" @@ -193,7 +194,11 @@ androidx-test-ext-junit = { module = "androidx.test.ext:junit", version = "1.3.0 androidx-test-runner = { module = "androidx.test:runner", version = "1.7.0" } androidx-test-espresso-core = { module = "androidx.test.espresso:espresso-core", version = "3.7.0" } junit = { module = "junit:junit", version = "4.13.2" } -mockk = { module = "io.mockk:mockk", version.ref = "mockk" } +mokkery-library = { module = "dev.mokkery:mokkery-runtime", version.ref = "mokkery" } +kotest-assertions = { module = "io.kotest:kotest-assertions-core", version.ref = "kotest" } +kotest-property = { module = "io.kotest:kotest-property", version.ref = "kotest" } +kotest-framework = { module = "io.kotest:kotest-framework-engine", version.ref = "kotest" } +kotest-runner-junit6 = { module = "io.kotest:kotest-runner-junit6", version.ref = "kotest" } robolectric = { module = "org.robolectric:robolectric", version = "4.16.1" } turbine = { module = "app.cash.turbine:turbine", version.ref = "turbine" } @@ -247,6 +252,7 @@ detekt-gradlePlugin = { module = "io.gitlab.arturbosch.detekt:detekt-gradle-plug firebase-crashlytics-gradlePlugin = { module = "com.google.firebase:firebase-crashlytics-gradle", version.ref = "firebase-crashlytics-gradle" } google-services-gradlePlugin = { module = "com.google.gms.google-services:com.google.gms.google-services.gradle.plugin", version.ref = "google-services-gradle" } koin-gradlePlugin = { module = "io.insert-koin.compiler.plugin:io.insert-koin.compiler.plugin.gradle.plugin", version.ref = "koin-plugin" } +mokkery-gradlePlugin = { module = "dev.mokkery:mokkery-gradle", version.ref = "mokkery" } kover-gradlePlugin = { module = "org.jetbrains.kotlinx.kover:org.jetbrains.kotlinx.kover.gradle.plugin", version.ref = "kover" } ksp-gradlePlugin = { module = "com.google.devtools.ksp:com.google.devtools.ksp.gradle.plugin", version.ref = "devtools-ksp" } secrets-gradlePlugin = {module = "com.google.android.secrets-gradle-plugin:com.google.android.secrets-gradle-plugin.gradle.plugin", version = "1.1.0"} @@ -269,6 +275,7 @@ kotlin-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref kotlin-parcelize = { id = "org.jetbrains.kotlin.plugin.parcelize", version.ref = "kotlin" } kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" } kover = { id = "org.jetbrains.kotlinx.kover", version.ref = "kover" } +mokkery = { id = "dev.mokkery", version.ref = "mokkery" } # Google devtools-ksp = { id = "com.google.devtools.ksp", version.ref = "devtools-ksp" }