如何在Kotlin中Mock Handler?Slot未初始化报错求助
问题解决:MockK Slot捕获Runnable时"lateinit property captured has not been initialized"错误
错误原因
你代码的核心问题是执行顺序颠倒:在调用Manager.myTesting()触发Handler的postDelayed方法之前,就尝试访问slotrunnable.captured,此时Slot还没有捕获到任何Runnable实例,自然会抛出未初始化的异常。
另外你的Handler Mock逻辑也存在问题:原代码是通过new Handler(Looper.getMainLooper())创建新的Handler实例,你直接mock一个Handler对象的话,原代码里的新Handler不会使用这个mock实例,导致Slot根本无法捕获调用。
修正后的完整测试代码
// 1. 声明Runnable类型的Slot val slotRunnable = slot<Runnable>() // 2. Mock Looper相关逻辑 mockkStatic(Looper::class) val looper = mockk<Looper> { every { thread } returns Thread.currentThread() } every { Looper.getMainLooper() } returns looper // 3. Mock Handler的构造方法,让原代码创建的Handler使用mock实例 val mockHandler = mockk<Handler>(relaxed = true) mockkConstructor(Handler::class) every { anyConstructed<Handler>().postDelayed(capture(slotRunnable), 100) } answers { true } // 4. 先执行目标方法,触发postDelayed调用,让Slot捕获Runnable Manager.myTesting() // 5. 此时Slot已捕获到Runnable,再执行run() slotRunnable.captured.run()
关键修正点
- 调整执行顺序:必须先调用
Manager.myTesting(),让原代码中的Handler触发postDelayed,Slot才能捕获到传入的Runnable,之后才能安全访问captured属性。 - 正确Mock Handler构造:使用
mockkConstructor(Handler::class)来拦截Handler的构造,确保原代码中new Handler(...)创建的实例是我们的mock对象,这样才能捕获到postDelayed的调用。 - 确保Slot实例正确初始化:显式创建
slot<Runnable>()实例,避免未初始化的问题。
内容的提问来源于stack exchange,提问作者Xuai
相关产品推荐
相关产品推荐

