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

Flutter GetX单元测试报Null非RxString子类型错误问题咨询

错误成因

使用Mockito生成的MockSwitchController是基于类接口生成的空实现模拟类,不会执行真实SwitchController的构造逻辑,也不会初始化类内部声明的成员变量。访问sut.selectedPill时,Mock对象对未打桩的属性默认返回null,但selectedPill的静态类型为非空的RxString(.obs语法生成的响应式字符串类型),null无法匹配非空RxString类型要求,因此抛出类型错误。
另外真实SwitchController初始化时会自动执行Get.put(DateNavigationController())注入依赖,Mock类不会执行这段逻辑,后续测试涉及关联依赖时也会触发异常。

修复方案

根据测试场景二选一即可:

方案1:直接使用真实Controller实例(适配当前测试场景)

当前测试仅校验Controller自身属性初始值,不需要Mock隔离依赖,直接实例化真实Controller即可,注意提前开启GetX测试模式避免依赖注入报错:

void main() {
  late SwitchController sut;

  setUp(() {
    // 开启GetX测试模式,跳过全局上下文校验
    Get.testMode = true;
    sut = SwitchController();
    sut.onInit();
  });

  tearDown(() {
    sut.dispose();
    // 清空GetX实例池,避免用例间状态污染
    Get.reset();
  });

  test('selectedPill初始值为week', () {
    expect(sut.selectedPill.value, "week");
  });
}

方案2:必须Mock Controller场景下手动打桩属性

如果后续测试需要隔离Controller其他逻辑、模拟特定返回行为,需要在访问属性前对响应式变量手动打桩:

  • 如果是手写Mock类,直接重写对应属性返回固定值即可:
class MockSwitchController extends Mock implements SwitchController {
  @override
  final RxString selectedPill = "week".obs;

  @override
  final RxInt labelIndex = 0.obs;
}
  • 如果是通过Mockito注解自动生成Mock类,在测试setUp阶段通过when语法打桩:
@GenerateMocks([SwitchController])
void main() {
  late MockSwitchController sut;

  setUp(() {
    Get.testMode = true;
    sut = MockSwitchController();
    // 手动给属性打桩
    when(() => sut.selectedPill).thenReturn("week".obs);
  });

  tearDown(() {
    sut.dispose();
    Get.reset();
  });

  test('selectedPill初始值为week', () {
    expect(sut.selectedPill.value, "week");
  });
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.02 08:42:28