Controller测试遇MockkException:AuthService.create无应答
问题原因与解决方法
核心原因:对象相等性不匹配
Mockk 默认通过对象的 equals() 方法匹配方法调用的参数。你的 signup 测试失败,本质是Controller 调用 authService.create() 时传入的 Account 实例,和测试代码里定义的 account 实例不是同一个对象,且 Account 类未正确重写 equals() 和 hashCode()——默认的 equals() 比较对象引用,只要不是同一个实例就会匹配失败。
而 signin 测试能成功,大概率是因为:
- signin 接口参数是简单类型(如用户名、密码字符串),不存在对象引用问题;
- 或你在 signin 测试中直接将同一个 Account 实例传给了 Controller,参数引用完全一致,所以匹配成功。
解决方法
1. 重写 Account 类的 equals() 和 hashCode()
让属性值相同的 Account 实例被视为相等,即使是不同实例,只要属性一致就能匹配。最简单的方式是用 Kotlin 数据类(自动生成 equals() 和 hashCode()):
data class Account(val username: String, val password: String)
如果不是数据类,手动重写:
class Account(val username: String, val password: String) { override fun equals(other: Any?): Boolean { if (this === other) return true if (javaClass != other?.javaClass) return false other as Account if (username != other.username) return false if (password != other.password) return false return true } override fun hashCode(): Int { var result = username.hashCode() result = 31 * result + password.hashCode() return result } }
2. 使用 Mockk 匹配器验证属性
如果不想修改 Account 类,可以用 match 匹配器检查传入对象的属性是否符合预期:
every { authService.create(match { it.username == account.username && it.password == account.password }) } returns expectedSignupResult
3. 捕获参数后断言属性
通过 slot 捕获调用时传入的 Account 实例,测试执行后验证其属性是否和预期一致:
// 定义捕获槽 val capturedAccount = slot<Account>() // 配置 mock 时捕获参数 every { authService.create(capture(capturedAccount)) } returns expectedSignupResult // 执行 signup 测试请求 mockMvc.perform(post("/signup")...).andExpect(status().isOk) // 断言捕获的实例属性 assertEquals(account.username, capturedAccount.captured.username) assertEquals(account.password, capturedAccount.captured.password)
内容的提问来源于stack exchange,提问作者Menyten
相关产品推荐
相关产品推荐

