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

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类,步骤如下:

  1. 在pubspec.yaml的dev_dependencies中添加依赖:
dev_dependencies:
  mockito: ^5.4.0
  build_runner: ^2.4.0
  1. 创建测试目录下的mock生成文件(比如test/mocks.dart):
import 'package:mockito/mockito.dart';
import '../lib/models/airport.dart'; // 替换为你的Airport类路径

@GenerateMocks([Airport])
void main() {}
  1. 运行生成命令:
flutter pub run build_runner build
  1. 在测试中使用生成的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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 20:51:13