Android中TextUtils.isDigitsOnly未Mock报错,求测试Mock方案
解决Android单元测试中TextUtils.isDigitsOnly未Mock的问题
你在实现输入验证逻辑时,通过Kotlin扩展调用了Android框架的TextUtils.isDigitsOnly方法,单元测试时出现以下错误:
Method isDigitsOnly in android.text.TextUtils not mocked
直接Mock TextUtils实例无效,因为isDigitsOnly是静态方法,Mockito默认无法Mock静态方法,且Mock实例对静态方法调用不起作用。以下是三种可行的解决方案:
方案1:封装Android框架依赖(推荐,符合依赖倒置原则)
核心思路是将Android框架的调用封装为独立接口,让验证类依赖抽象接口而非具体的Android工具类,测试时即可轻松Mock接口实现。
步骤1:创建封装接口与实现
// 抽象数字验证逻辑的接口 interface StringValidator { fun isDigitsOnly(input: String): Boolean } // 生产环境实现,调用Android的TextUtils class AndroidStringValidator : StringValidator { override fun isDigitsOnly(input: String): Boolean { return TextUtils.isDigitsOnly(input) } }
步骤2:修改验证类,注入接口依赖
class ValidationInputImpl( private val stringValidator: StringValidator = AndroidStringValidator() ) { fun isDigitsOnly(size: String): Boolean { return !size.trim().let { stringValidator.isDigitsOnly(it) } } operator fun invoke(input: String): ValidationResult { return if (isDigitsOnly(input)) { ValidationResult.Failure } else { ValidationResult.Success } } } // 假设你的ValidationResult定义 sealed class ValidationResult { object Success : ValidationResult() object Failure : ValidationResult() }
步骤3:测试类中Mock接口
@RunWith(MockitoJUnitRunner::class) class ValidationInputImplTest { @Mock private lateinit var mockStringValidator: StringValidator private lateinit var validationInputImpl: ValidationInputImpl @Before fun setUp() { validationInputImpl = ValidationInputImpl(mockStringValidator) } @Test fun `contains only digits returns success`() { val input = "66" `when`(mockStringValidator.isDigitsOnly(input.trim())).thenReturn(true) val result = validationInputImpl(input) assertTrue(result is ValidationResult.Success) } @Test fun `contains non-digit characters returns failure`() { val input = "66a" `when`(mockStringValidator.isDigitsOnly(input.trim())).thenReturn(false) val result = validationInputImpl(input) assertTrue(result is ValidationResult.Failure) } }
方案2:使用PowerMockMock静态方法
如果不想修改原有代码结构,可以用PowerMock直接Mock静态方法,需额外配置依赖:
步骤1:添加PowerMock依赖
在Module级别的build.gradle中添加:
testImplementation "org.powermock:powermock-module-junit4:2.0.9" testImplementation "org.powermock:powermock-api-mockito2:2.0.9"
步骤2:修改测试类
@RunWith(PowerMockRunner::class) @PrepareForTest(TextUtils::class) // 指定要Mock的静态类 class ValidationInputImplTest { private lateinit var validationInputImpl: ValidationInputImpl @Before fun setUp() { validationInputImpl = ValidationInputImpl() PowerMockito.mockStatic(TextUtils::class.java) } @Test fun `contains only digits returns success`() { val input = "66" PowerMockito.`when`(TextUtils.isDigitsOnly(input.trim())).thenReturn(true) val result = validationInputImpl(input) assertTrue(result is ValidationResult.Success) } }
方案3:纯Kotlin实现数字验证(无需依赖Android框架)
如果验证逻辑简单,可直接用纯Kotlin实现数字判断,完全脱离Android框架,测试无需Mock:
修改验证类逻辑:
override fun isDigitsOnly(size: String): Boolean { return !size.trim().all { it.isDigit() } }
对应的单元测试:
@RunWith(MockitoJUnitRunner::class) class ValidationInputImplTest { private lateinit var validationInputImpl: ValidationInputImpl @Before fun setUp() { validationInputImpl = ValidationInputImpl() } @Test fun `contains only digits returns success`() { val input = "66" val result = validationInputImpl(input) assertTrue(result is ValidationResult.Success) } }
内容的提问来源于stack exchange,提问作者Omar Redani
相关产品推荐
相关产品推荐

