MVVMHabit框架单元测试指南:ViewModel与Repository测试
测试环境准备
MVVMHabit框架的单元测试基于JUnit实现,项目中默认提供了测试示例类ExampleUnitTest.java,包含基础的测试用例结构。该类位于app/src/test/java/com/goldze/mvvmhabit目录下,提供了加法运算的测试示例,可作为测试类编写的模板。
ViewModel测试策略
核心测试目标
ViewModel作为业务逻辑核心,需重点测试数据处理、状态管理和命令响应。框架中典型的ViewModel包括:
- LoginViewModel:处理登录状态与用户输入验证
- NetWorkViewModel:管理网络请求与数据加载
- FormViewModel:处理表单数据验证与提交
测试实现步骤
- 初始化ViewModel:通过构造函数或工厂模式创建实例,必要时传入模拟依赖
- 触发业务方法:调用ViewModel中的命令方法(如登录、数据加载)
- 验证状态变化:检查LiveData对象的值是否符合预期
// LoginViewModel测试示例
public class LoginViewModelTest {
private LoginViewModel viewModel;
private TestObserver<Boolean> loginStatusObserver;
@Before
public void setup() {
// 创建ViewModel实例,注入模拟的Repository
viewModel = new LoginViewModel(new MockDemoRepository());
// 订阅LiveData变化
loginStatusObserver = viewModel.loginStatus.observeForever();
}
@Test
public void testValidLogin() {
// 执行登录命令
viewModel.loginCommand.execute(new LoginEntity("validUser", "validPass"));
// 验证登录状态为成功
assertTrue(loginStatusObserver.valueAt(0));
}
@After
public void teardown() {
loginStatusObserver.dispose();
}
}
Repository测试指南
测试架构解析
Repository层实现数据访问统一接口,典型实现如DemoRepository.java,需测试本地存储与网络请求的协同工作。该类通过组合HttpDataSource和LocalDataSource实现数据读写,测试需验证:
- 本地缓存与网络数据的一致性
- 异常处理机制(如网络错误时的降级策略)
测试实现示例
// DemoRepository测试示例
public class DemoRepositoryTest {
private DemoRepository repository;
private MockHttpDataSource mockHttpDataSource;
private MockLocalDataSource mockLocalDataSource;
@Before
public void setup() {
// 创建模拟数据源
mockHttpDataSource = new MockHttpDataSource();
mockLocalDataSource = new MockLocalDataSource();
// 初始化Repository
repository = DemoRepository.getInstance(
mockHttpDataSource,
mockLocalDataSource
);
}
@Test
public void testDataCaching() {
// 模拟网络数据
DemoEntity mockEntity = new DemoEntity();
mockHttpDataSource.setDemoEntity(mockEntity);
// 执行数据请求
TestObserver<DemoEntity> observer = repository.demoGet().test();
// 验证数据返回与本地缓存
observer.assertValue(mockEntity);
assertEquals(mockEntity, mockLocalDataSource.getCachedData());
}
@After
public void teardown() {
DemoRepository.destroyInstance();
}
}
测试最佳实践
依赖注入与模拟对象
- 使用Mock框架(如Mockito)模拟外部依赖
- 通过构造函数注入模拟对象,避免真实网络请求和数据库操作
- 对BaseViewModel的子类,重点测试
BindingCommand的执行结果
测试覆盖率提升
- 重点覆盖异常场景(如网络超时、数据解析错误)
- 验证LiveData的生命周期管理(如数据粘性问题处理)
- 测试ViewModel的
onDestroy()方法是否正确释放资源
测试工具集成
- 在Android Studio中通过
Run with Coverage查看测试覆盖率 - 使用Espresso进行UI层集成测试,与单元测试形成互补
- 测试结果可通过
AndroidTestOrchestrator实现隔离执行
常见问题解决方案
测试数据准备
当测试需要复杂实体类时,可使用项目中的DemoEntity.java作为模板创建测试数据,或使用Builder模式简化对象构建。
异步测试处理
ViewModel中的异步操作(如网络请求)需使用RxJava的TestScheduler或LiveData的InstantTaskExecutorRule确保测试同步执行:
@Rule
public InstantTaskExecutorRule instantTaskRule = new InstantTaskExecutorRule();
静态单例处理
针对Repository的单例模式(如DemoRepository.getInstance()),测试中需使用@VisibleForTesting注解的destroyInstance()方法重置状态,避免测试相互干扰。
总结
MVVMHabit框架的单元测试需重点关注ViewModel的业务逻辑验证和Repository的数据流程测试。通过模拟依赖、验证状态变化和覆盖异常场景,可有效提升代码质量。结合框架提供的基础测试类和示例代码,开发者可快速构建完善的测试体系,确保应用在迭代过程中的稳定性。
测试用例应与业务代码同步维护,建议遵循"测试驱动开发"模式,在实现功能前先编写测试用例,以提高代码的可测试性和健壮性。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考




