You need to enable JavaScript to run this app. Kotlin安卓单元测试中如何设置被测函数内部局部变量deviceList的值
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin安卓单元测试中如何设置被测函数内部局部变量deviceList的值

安卓单元测试控制被测函数内部deviceList取值的实现方法

你无法直接修改函数运行时的内部局部变量,但可以通过Mock该局部变量的上游依赖,间接控制它的取值,具体操作如下:


实现原理

函数内的deviceList来源于UsbManager的deviceList属性,而UsbManager是从传入的Context参数获取的,只要Mock这两个依赖的返回值,就能完全控制deviceList的取值。


前置依赖配置

在模块级build.gradle的dependencies块中添加测试依赖:

testImplementation "org.mockito:mockito-core:4.11.0"
// 用于Mock安卓系统的final类(如UsbManager)
testImplementation "org.mockito:mockito-inline:4.11.0"
testImplementation "org.mockito.kotlin:mockito-kotlin:4.1.0"
testImplementation "junit:junit:4.13.2"
testImplementation "org.hamcrest:hamcrest-library:2.2"

测试代码示例

你之前使用的ApplicationProvider获取的是真实运行环境的Context,无法自定义返回系统服务的结果,需要替换为Mock的Context,完整测试代码如下:

import org.junit.Test
import org.mockito.Mock
import org.mockito.junit.MockitoJUnitRunner
import org.mockito.kotlin.whenever
import org.hamcrest.CoreMatchers.`is`
import org.hamcrest.MatcherAssert.assertThat
import android.content.Context
import android.hardware.usb.UsbManager
import android.hardware.usb.UsbDevice
import org.junit.runner.RunWith

@RunWith(MockitoJUnitRunner::class)
class SampleTest {

    @Mock
    private lateinit var mockContext: Context
    @Mock
    private lateinit var mockUsbManager: UsbManager
    @Mock
    private lateinit var mockUsbDevice: UsbDevice

    // 此处替换为你自己的被测类实例
    private lateinit var sample: YourBusinessClass

    @Test
    fun `needToBeTested 返回1当存在厂商自定义类USB设备时`() {
        // 1. 构造你需要的deviceList
        val testDeviceList = HashMap<String, UsbDevice>()
        // 配置Mock USB设备的属性,比如deviceClass设为255
        whenever(mockUsbDevice.deviceClass).thenReturn(255)
        whenever(mockUsbManager.hasPermission(mockUsbDevice)).thenReturn(true)
        testDeviceList["test_device"] = mockUsbDevice

        // 2. 配置UsbManager返回自定义的deviceList
        whenever(mockUsbManager.deviceList).thenReturn(testDeviceList)

        // 3. 配置Context返回Mock的UsbManager
        whenever(mockContext.getSystemService(Context.USB_SERVICE)).thenReturn(mockUsbManager)

        // 4. 执行测试并校验结果
        val result = sample.needToBeTested(mockContext)
        assertThat(result, `is`(1))
    }

    @Test
    fun `needToBeTested 返回0当无USB设备时`() {
        // 直接返回空的deviceList即可触发空设备分支
        whenever(mockUsbManager.deviceList).thenReturn(emptyMap())
        whenever(mockContext.getSystemService(Context.USB_SERVICE)).thenReturn(mockUsbManager)

        val result = sample.needToBeTested(mockContext)
        assertThat(result, `is`(0))
    }
}

可选方案

如果你使用Robolectric做本地单元测试,也可以用ShadowUsbManager直接配置设备列表,不需要手动Mock Context和UsbManager:

val usbManager = ApplicationProvider.getApplicationContext<Context>().getSystemService(Context.USB_SERVICE) as UsbManager
val shadowUsbManager = shadowOf(usbManager)
val testDeviceList = HashMap<String, UsbDevice>()
// 配置你的测试设备后传入即可
shadowUsbManager.setDevices(testDeviceList)

内容的提问来源于stack exchange,提问作者BS22

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.18 22:06:00