采用koin 依赖注入进行viewmodel单元测试

Groovy 复制代码
koin = "3.6.0-Beta4"
koinComposeMultiplatform = "1.2.0-Beta4"
truth = "1.0.1"
mockito = "2.21.0"
mockk = "1.13.2"
kotinx="1.7.0"



koin-core = { module = "io.insert-koin:koin-core", version.ref = "koin" }
koin-compose = { module = "io.insert-koin:koin-compose", version.ref = "koinComposeMultiplatform" }
koin-compose-viewmodel = { module = "io.insert-koin:koin-compose-viewmodel", version.ref = "koinComposeMultiplatform" }

kotlinx-coroutines={module = "org.jetbrains.kotlinx:kotlinx-coroutines-test",version.ref="kotinx"}
kotlin-test-junit = { module = "org.jetbrains.kotlin:kotlin-test-junit", version.ref = "kotlin" }
koin-test = { module = "io.insert-koin:koin-test", version.ref = "koin" }
koin-test-junit4 = { module = "io.insert-koin:koin-test-junit4", version.ref = "koin" }

google-truth = { module = "com.google.truth:truth", version.ref = "truth" }
mockito-core = { module = "org.mockito:mockito-core", version.ref = "mockito" }
mockk = { module = "io.mockk:mockk", version.ref = "mockk" }

添加依赖

Kotlin 复制代码
  val desktopTest by getting
        desktopTest.dependencies {
            implementation(libs.kotlin.test)
            implementation(libs.koin.test)
            implementation(libs.koin.test.junit4)
            implementation(libs.kotlinx.coroutines)
            implementation(libs.google.truth)
            implementation(libs.mockito.core)
            implementation(libs.mockk)
        }

以登录测试为例

测试class要继承 KoinTest

Kotlin 复制代码
class LoginByPwdOrCardViewModelTest : KoinTest {}

在测试开始时,对koin进行初始化

Kotlin 复制代码
    @BeforeTest
    fun setUp() {
        initTestKoin()
    }

InitKoin.kt
fun initTestKoin(config: KoinAppDeclaration? = null) {
    startKoin {
        config?.invoke(this)
        modules( testModule, viewModelModule)
    }
}



Modules.kt

val testModule = module {
    singleOf(::TestDeskTopRepository).bind<DeskTopRepository>()
}


val viewModelModule= module {
//    viewModelOf(::LoginByPwdOrCardViewModel)\
    factory { LoginByPwdOrCardViewModel(get()) } //每次都是重新生成

}

桌面开发的viewmodel 和Android的viewmodel 创建方式不一样,Android有屏幕旋转,生命周期等感知

结束清理工作

Kotlin 复制代码
    @AfterTest
    fun tearUp() {
        stopKoin()
    }

这样就可以通过注入的方式初始化viewmode

private val viewModel by inject<LoginByPwdOrCardViewModel>()

做几个测试示例

Kotlin 复制代码
 @Test
    fun testNeedAdminNormalUser_emitError() = runTest {
        viewModel.needAdmin.value = true//需要管理员权限
        viewModel.accountInputState.value = "linlian"
        viewModel.passwordInputState.value = "2"
        viewModel.loginByAccount()
        val event = viewModel.error.first() //shareflow 会阻塞等待
        assertThat(event.getContentIfNotHandled()?.status).isEqualTo(Status.ERROR)
    }

    @Test
    fun testLoginValidUser_emitError() = runTest {
        viewModel.accountInputState.value = "Invalid"
        viewModel.passwordInputState.value = "2"
        viewModel.loginByAccount()
        val event = viewModel.error.first() //shareflow 会阻塞等待
        assertThat(event.getContentIfNotHandled()?.status).isEqualTo(Status.ERROR)
    }

    @Test
    fun testNeedAdminAdminUser_userInfoNotNull() = runTest {
        viewModel.needAdmin.value = true//需要管理员权限
        viewModel.accountInputState.value = "Admin"
        viewModel.passwordInputState.value = "2"
        val job = viewModel.loginByAccount()
        job.join()
        val userInfo = LoginUserUtils.userInfoFlow.first() //stateflow不会阻塞等待
        assertThat(userInfo).isNotNull()
    }
相关推荐
ly768919 小时前
前端测试完整指南:从单元测试、组件测试到端到端测试与 CI/CD
前端·ci/cd·单元测试
咖啡星人k21 小时前
2026 AI 自动化测试:让 AI 帮你写用例、跑测试、修 Bug(MonkeyCode 云端实战)
人工智能·功能测试·单元测试·测试用例·bug·集成测试
花椒技术1 天前
不是跑通一次 Demo:花椒 QA 怎样把真机 UI 自动化做成回归流程
ios·单元测试·测试
边吃番茄边敲代码2 天前
企业智能助手Agent 安全测试,包含Prompt Injection 和越权工具调用
人工智能·python·功能测试·ai·单元测试·prompt·模块测试
Lost of 程序猿2 天前
ASP.NET Core 测试实战:从单元测试到集成测试的全链路质量保障
单元测试·asp.net·集成测试
hh9502 天前
gent Plan × DeepSeek Harness Agent 单元测试与行为回归框架
人工智能·数据挖掘·回归·单元测试·agent plan·adg成都社区·adg社区
川石课堂软件测试3 天前
自动化测试常见的异常处理
python·jmeter·mysql·docker·容器·单元测试·grafana
智码看视界5 天前
Day 56:AI辅助开发全面提效:Copilot + Cursor的Java开发
java·单元测试·copilot·cursor·后端开发·代码审查·ai辅助开发
深维AI随笔6 天前
《构建之法》| 第二章个人技术和流程:单元测试不是“可选“,而是“必需“
单元测试·log4j·apache