4. 编写第一个测试用例:@Test注解与基础断言
说句实话,刚接触 Kotlin 测试时,我最大的困惑就是——到底怎么写一个能跑起来的测试? 其实核心就三样东西:一个注解、两个断言方法。今天咱们就把它们彻底讲透。
4.1 @Test 注解:让函数变身测试
在 Kotlin 里,测试方法不过是一个普通函数,但前面要加上 @Test 注解。嗯,就像给函数贴了个“我是测试”的标签。JUnit 运行时只会执行贴了标签的函数。
核心规则:被 @Test 标记的函数必须用 fun 声明,且不能有参数(参数化测试是另一回事,咱们后面讲)。
举个最简单的例子——
import org.junit.Test
import kotlin.test.*
class MyFirstTest {
@Test
fun testAddition() {
assertEquals(4, 2 + 2)
}
}
这个测试在 JUnit 4 环境下就能直接运行。你可能注意到了,我直接导入了 kotlin.test.*,这包里的断言函数用起来更顺手。
我的小习惯:测试函数命名尽量用 testXxx 或 `测试什么功能`。我个人偏爱后者,因为反引号里可以写中文,一眼就能看出测试点。不过团队约定优先哈。
4.2 assertTrue:验证“真”条件
assertTrue 说白了就是“你这个表达式必须为 true,不然就给我失败”。我在项目中遇到过最典型的使用场景——检查某个列表不为空:
@Test
fun testListNotEmpty() {
val list = listOf("apple", "banana")
assertTrue(list.isNotEmpty())
}
如果你想让失败信息更友好,可以加第二个参数:
assertTrue(list.isNotEmpty(), "列表居然为空了,快检查代码!")
4.3 assertEquals:精确对比两个值
这是用的最多的断言。它判断两个对象是否 相等(通过 equals 方法,不是引用相同)。注意:Kotlin 的 assertEquals 参数顺序是 expected, actual,千万别搞反。为什么?因为失败信息会告诉你“期望是XX,实际是YY”,顺序错了你会被误导。
@Test
fun testStringUppercase() {
val result = "hello".uppercase()
assertEquals("HELLO", result)
}
我曾经踩过的坑:老习惯把 actual 放前面,结果某次对比两个长字符串,失败信息显示“期望: abc...,实际: xyz...”,我 debug 了半小时才发现参数写反了。真的,顺序很重要。
4.4 两个断言的对比
| 断言 | 用途 | 失败信息特点 | 最佳搭档 |
|---|---|---|---|
assertTrue |
验证布尔表达式为真 | 默认只输出“expected true but was false” | 自定义消息 |
assertEquals |
验证两个对象相等 | 输出期望值和实际值 | 复杂对象请重写 equals |
你可能想问:什么时候用 assertTrue?举个现实例子——验证一个函数返回的 Result 是否成功:
@Test
fun testApiResponseSuccess() {
val response = someApi.call()
assertTrue(response.isSuccess, "API 调用失败")
}
而当你需要精确比对数值、字符串、对象时,assertEquals 更合适。
4.5 完整的测试用例骨架
我们来写一个综合的例子。假设有一个计算器类,我们要测加法:
class Calculator {
fun add(a: Int, b: Int): Int = a + b
}
class CalculatorTest {
private val calc = Calculator()
@Test
fun testAddPositiveNumbers() {
val result = calc.add(3, 5)
assertEquals(8, result, "3 + 5 应该等于 8")
}
@Test
fun testAddWithZero() {
assertTrue(calc.add(0, 10) == 10, "加 0 结果应不变")
}
@Test
fun testAddNegativeNumbers() {
val sum = calc.add(-2, -3)
assertEquals(-5, sum)
}
}
注意:每个 @Test 方法都是独立的。JUnit 会为每个测试新建一个测试类实例,所以你不用担心测试之间互相干扰。这特性很好用。
4.6 本章知识点全景图
4.7 写给初学者的几条提醒
- 不要在一个测试里写多个断言——虽然技术上允许,但第一个断言失败后后面的代码就不跑了,你无法知道后续是否也有 bug。我建议一个测试只验证一个行为。
- 善用描述性函数名:比如
testDepositIncreasesBalance,失败了你能从名字大概猜到原因。 - 运行测试:IntelliJ 里可以直接点方法名左侧的绿色三角,也可以右键类名运行整个测试类。试试看?