Flutter/Dart中如何Stub Freezed数据类的Getter或方法?
解决Freezed类Mock getter方法返回Null的问题
问题背景
我定义了一个Freezed数据类Airport,其中包含一个getter方法allIls,用于便捷获取嵌套的Ils元素:
@freezed class Airport with _$Airport { const Airport._(); const factory Airport({ required String identifier, required String type, required List<Runway> runways, }) = _Airport; List<Ils> get allIls => runways .map((runway) => runway.allIls) .expand((ils) => ils) .toList(); }
测试时不想填充合法的runways数据,希望直接Stub getter方法allIls使其返回指定对象列表,但尝试两种方案都报错:type 'Null' is not a subtype of type 'List<Ils>':
- 创建
MockAirport类后,使用when(airport.allIls).thenReturn(ilsList) - 将getter改为普通方法
allIls2(),使用when(airport.allIls2.call()).thenReturn(ilsList)
解决方案
原因分析
Mock类默认返回null,但allIls的返回类型是非空的List<Ils>,类型不匹配导致运行时错误;同时Freezed生成的类结构会让手动创建的Mock无法正确覆盖getter的默认行为。
方案1:手动修改Mock类,指定默认返回值
在自定义的MockAirport类中重写allIls getter,通过noSuchMethod指定默认返回空列表,这样后续Stub就能正常覆盖:
class MockAirport extends Mock implements Airport { @override List<Ils> get allIls => super.noSuchMethod( Invocation.getter(#allIls), returnValue: <Ils>[], ) as List<Ils>; }
测试代码无需改动,when(airport.allIls).thenReturn(ilsList)即可生效。
方案2:使用mockito代码生成工具生成Mock类
利用mockito的代码生成功能,自动生成能适配非空类型的Mock类,步骤如下:
- 在
pubspec.yaml的dev_dependencies中添加依赖:
dev_dependencies: mockito: ^5.4.0 build_runner: ^2.4.0
- 创建测试目录下的mock生成文件(比如
test/mocks.dart):
import 'package:mockito/mockito.dart'; import '../lib/models/airport.dart'; // 替换为你的Airport类路径 @GenerateMocks([Airport]) void main() {}
- 运行生成命令:
flutter pub run build_runner build
- 在测试中使用生成的
MockAirport类:
import 'mocks.dart'; test('测试Airport的allIls getter', () async { final airport = MockAirport(); final ilsList = [ils1, ils2]; when(airport.allIls).thenReturn(ilsList); expect(airport.allIls, equals(ilsList)); });
方案3:构造带模拟Runway的Airport实例(备选)
如果只是需要验证allIls的逻辑,也可以直接构造Airport实例,同时Mock嵌套的Runway对象(但这需要填充runways字段,不符合原需求,仅作备选):
final mockRunway = MockRunway(); when(mockRunway.allIls).thenReturn([ils1, ils2]); final airport = Airport( identifier: 'TEST', type: 'large_airport', runways: [mockRunway], ); expect(airport.allIls, equals([ils1, ils2]));
内容的提问来源于stack exchange,提问作者tmaihoff
相关产品推荐
相关产品推荐

