You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Mockito测试LoginViewModel出现NullPointerException问题求助

问题原因与解决方案

核心问题定位

  • 问题1:测试类中LoginViewModel字段被错误添加了@Mock注解
    我们需要测试真实的ViewModel业务逻辑,不需要mock它本身,这个注解不仅多余,还可能和@Before里的手动实例化逻辑冲突。
  • 问题2:系统邮箱正则类Patterns.EMAIL_ADDRESS在本地JVM单元测试中为空
    android.util.Patterns是Android SDK提供的类,本地单元测试运行在JVM环境,没有Android运行时支持,该类的默认实现是空桩,调用Patterns.EMAIL_ADDRESS会直接返回null,调用matcher方法就会触发NullPointerException。

修复步骤

步骤1:清理测试类的错误注解

删掉viewModel字段上的@Mock注解,修改后测试类的字段声明部分如下:

@RunWith(MockitoJUnitRunner::class)
class LoginViewModelTest {

    @Mock
    private lateinit var repository: LoginRepository

    // 此处移除@Mock注解,使用手动创建的真实实例
    private lateinit var viewModel: LoginViewModel

    @Mock
    private lateinit var preferences: Preferences

    @Rule
    @JvmField
    val instantTaskExecutorRule = InstantTaskExecutorRule()

    val invalidEmail = ""
    val invalidPassword = ""
    val validEmail = "test@email.com"
    val validPassword = "test12345"
    // 其余逻辑保持不变
}

步骤2:解决Patterns.EMAIL_ADDRESS的依赖问题

有两种可选方案:

方案A:使用Robolectric提供Android运行时环境(推荐)

Robolectric可以在本地JVM上模拟Android运行环境,让系统类可以正常调用:

  1. 模块build.gradle添加Robolectric依赖
testImplementation "org.robolectric:robolectric:4.9"
  1. 把测试类的@RunWith注解改为@RunWith(RobolectricTestRunner::class)即可。

方案B:替换系统邮箱正则,不依赖Android SDK

如果不想引入Robolectric,可以直接把邮箱校验逻辑换成自定义正则,修改LoginViewModel的isEmailValid方法:

private fun isEmailValid(email: String): Boolean {
    // 自定义邮箱正则,替换系统的Patterns.EMAIL_ADDRESS
    val emailPattern = "^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}$"
    return Pattern.compile(emailPattern).matcher(email).matches()
}

可选优化

你当前用空字符串作为非法邮箱,修复后可以补充更多场景,比如格式错误的邮箱(test@.com、test.com等),覆盖更多异常情况。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 15:27:00