Kotlin 测试:从入门到精通的单元测试、集成测试和端到端测试
\n\n现代 Kotlin 开发需要系统化的测试方法。无论您是在编写基于 Ktor 的后端应用还是 Android 移动应用,高质量的代码测试覆盖率都是项目稳定性和可预测性的关键。在本文中,我们将探讨三个测试级别:单元测试、集成测试和端到端测试。您将了解使用哪些工具、如何编写高效的 Kotlin 测试以及如何避免常见错误。
\n\n1. Kotlin 单元测试:基础中的基础
\n\n单元测试在隔离外部依赖的情况下,验证单个函数、类或方法的工作情况。在 Kotlin 中,最常使用 JUnit 5 框架结合模拟库 MockK 来实现。
\n\n项目配置
\n\n在 build.gradle.kts 中添加依赖:
dependencies {\n testImplementation("org.junit.jupiter:junit-jupiter:5.10.0")\n testImplementation("io.mockk:mockk:1.13.8")\n}\n\n\n单元测试示例
\n\n假设我们有一个简单的折扣计算服务:
\n\nclass DiscountService {\n fun applyDiscount(price: Double, discountPercent: Int): Double {\n require(discountPercent in 0..100) { "折扣百分比必须在 0 到 100 之间" }\n return price * (100 - discountPercent) / 100\n }\n}\n\n\n该服务的测试:
\n\nimport org.junit.jupiter.api.Assertions.*\nimport org.junit.jupiter.api.Test\nimport org.junit.jupiter.api.assertThrows\n\nclass DiscountServiceTest {\n\n private val service = DiscountService()\n\n @Test\n fun `applyDiscount 正确计算 50% 折扣`() {\n val result = service.applyDiscount(1000.0, 50)\n assertEquals(500.0, result, 0.001)\n }\n\n @Test\n fun `applyDiscount 在百分比无效时抛出异常`() {\n assertThrows<IllegalArgumentException> {\n service.applyDiscount(100.0, 150)\n }\n }\n}\n\n\n提示: 使用 assertThrows 验证异常,并用清晰的字符串命名测试——这能提高报告的可读性。
使用 MockK 进行模拟
\n\n当您的类依赖其他组件(例如仓库或 API)时,请使用模拟:
\n\nclass OrderService(private val paymentGateway: PaymentGateway) {\n fun processOrder(amount: Double): String {\n if (paymentGateway.charge(amount)) {\n return "支付成功"\n }\n return "支付失败"\n }\n}\n\n// 测试\n@Test\nfun `processOrder 在支付成功时返回成功`() {\n val mockGateway = mockk<PaymentGateway>()\n every { mockGateway.charge(any()) } returns true\n\n val service = OrderService(mockGateway)\n val result = service.processOrder(500.0)\n\n assertEquals("支付成功", result)\n verify { mockGateway.charge(500.0) }\n}\n\n\n2. 集成测试:验证组件间的交互
\n\n集成测试验证系统不同部分如何协同工作:数据库、外部 API、文件系统。对于 Kotlin,Testcontainers 是一个绝佳选择——它是在测试期间启动 Docker 容器的库。
\n\nPostgreSQL 数据库示例
\n\n添加依赖:
\n\ntestImplementation("org.testcontainers:testcontainers:1.19.3")\ntestImplementation("org.testcontainers:postgresql:1.19.3")\n\n\n编写 DAO 层的测试:
\n\nclass UserRepositoryIntegrationTest {\n\n companion object {\n private val postgres = PostgreSQLContainer<Nothing>("postgres:15").apply {\n withDatabaseName("testdb")\n withUsername("test")\n withPassword("test")\n start()\n