如何对函数返回的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
相关产品推荐
相关产品推荐

