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

如何对函数返回的Stream数据流进行正确的单元测试?

问题原因
  • 引用匹配失效:Dart自定义类默认的相等判断是引用比较,你在测试代码里创建的Resource.loading()、Resource.error("")和Stream实际发射的Resource实例是独立的对象,哪怕属性完全一致也会被判定为不相等。
  • 错误值不匹配:测试用例中错误实例的入参是空字符串,而代码实际发射的错误值是NetworkErrors.NO_INTERNET常量,内容不一致也会导致匹配失败。
  • 缺少异步等待:针对Stream的expect调用返回的是Future,如果不加await,测试会在Stream发射完全部事件之前就结束,也可能触发异常。
解决方案

方案1:重写Resource类的相等判断(推荐)

给Resource类重写==运算符和hashCode,让相等判断基于属性值而非引用:

import 'package:flutter/foundation.dart';

class Resource<T> {
  T? data;
  String? error;

  Resource._({this.data, this.error});
  factory Resource.success(T? data) => Resource._(data: data);
  factory Resource.error(String error) => Resource._(error: error);
  factory Resource.loading() => Resource._(); 

  @override
  bool operator ==(Object other) =>
      identical(this, other) ||
      other is Resource &&
          runtimeType == other.runtimeType &&
          // 集合类数据用深度比较
          ((data is List && listEquals(data as List, other.data as List)) || data == other.data) &&
          error == other.error;

  @override
  int get hashCode => data.hashCode ^ error.hashCode;
}

修改测试用例,补全await和正确的错误值:

test('Loading then error', () async {
  final categoriesRepo = CategoriesRepo();
  await expect(
    categoriesRepo.getAllCategories(),
    emitsInOrder([
      Resource<List<Category>>.loading(),
      Resource<List<Category>>.error(NetworkErrors.NO_INTERNET),
      emitsDone
    ]),
  );
});

方案2:用属性匹配器跳过实例比较

如果你不想修改原类,可直接用predicate匹配器校验属性即可:

test('Loading then error', () async {
  final categoriesRepo = CategoriesRepo();
  await expect(
    categoriesRepo.getAllCategories(),
    emitsInOrder([
      predicate<Resource<List<Category>>>((res) => res.error == null && res.data == null),
      predicate<Resource<List<Category>>>((res) => res.error == NetworkErrors.NO_INTERNET && res.data == null),
      emitsDone
    ]),
  );
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 10:45:04