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

Flutter测试中如何正确校验MaterialStateProperty属性值?

问题描述
  • 实现了可通过参数指定elevation属性的ElevatedButton组件,核心实现代码:
child: ElevatedButton(
  key: const Key('MyButton'),
  onPressed: () {},
  child: Text('My Button'),
  style: ButtonStyle(
    elevation: MaterialStateProperty.all<double>(2.0),
  ),
), ...
  • 尝试编写测试用例校验按钮的elevation属性,最初编写的测试代码:
final button = tester
    .widget<ElevatedButton>(find.byKey(Key('NewSessionsElevatedButton')));
expect(button.style.elevation, MaterialStateProperty.all<double>(2.0));
  • 运行测试时抛出失败异常,日志显示预期值和实际值的打印结果完全一致,但测试仍然判定不通过,错误日志如下:
══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following TestFailure object was thrown running a test:
  Expected: _MaterialStatePropertyAll<double>:<MaterialStateProperty.all(2.0)>
  Actual: _MaterialStatePropertyAll<double>:<MaterialStateProperty.all(2.0)>
  • 查阅官方相关测试用例后未找到清晰的示例,需要明确MaterialStateProperty类型属性的正确测试方式。
失败原因

MaterialStateProperty.all()构造返回_MaterialStatePropertyAll私有类实例,该类未重写==操作符与hashCode getter,默认继承Object的相等判断逻辑为引用相等:即便两个实例包裹的属性值完全一致,只要不是同一个实例,直接做相等判断就会返回false,这就是日志打印内容完全一致但测试失败的核心原因。
另外测试代码存在笔误:组件定义时传入的key为MyButton,测试中查找的key为NewSessionsElevatedButton,运行时会先触发找不到组件的错误,需要先将两处key修正为一致。

正确测试方案

通用的标准测试写法为:不直接比较MaterialStateProperty实例,而是调用实例的resolve()方法,传入待校验的组件状态集合,拿到解析后的实际属性值再做断言。这种写法不耦合属性实现逻辑,无论是固定值的MaterialStateProperty.all(),还是根据状态动态返回值的MaterialStateProperty.resolveWith()都可以正常校验。

校验默认常态下的属性值

传入空状态集合,即可拿到组件无交互(未按下、未禁用、未聚焦、未选中)时的属性值:

// 先修正key,和组件定义保持一致
final button = tester.widget<ElevatedButton>(find.byKey(const Key('MyButton')));
// 解析默认状态下的elevation值
final defaultElevation = button.style?.elevation?.resolve({});
expect(defaultElevation, 2.0);

校验特定交互状态下的属性值

如果需要校验按钮按下、禁用、聚焦等特定状态下的属性值,只需将对应状态传入resolve()的参数集合即可,例如校验按下状态的elevation:

final pressedElevation = button.style?.elevation?.resolve({MaterialState.pressed});
// 替换为对应状态下的预期elevation值做断言
expect(pressedElevation, 4.0);

如果需要明确校验属性的实现类型为固定值的MaterialStatePropertyAll,也可以通过类型断言后取内部value值判断,但这种写法耦合实现逻辑,不推荐使用:

final elevationProperty = button.style?.elevation;
expect(elevationProperty, isA<MaterialStatePropertyAll<double>>());
final fixedElevation = (elevationProperty as MaterialStatePropertyAll<double>).value;
expect(fixedElevation, 2.0);

内容的提问来源于stack exchange,提问作者Miguel de Sousa

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 17:54:30