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
相关产品推荐
相关产品推荐

