【问题标题】:Dart async* stream breaks randomly in unit testsDart async* 流在单元测试中随机中断
【发布时间】:2020-11-25 03:40:24
【问题描述】:

一个简单的用例,我从服务器中获取数据列表。 我想将其转换为流。在此之前,我想在单元测试中测试事情是否正常。

环境

  • Flutter(通道稳定,1.22.4,在 Linux 上)
  • Dart SDK 版本:2.10.4(稳定)

以下是合并在一个文件中的简化代码。

import 'package:flutter_test/flutter_test.dart';

class BeanList<T> {
  final List<T> list;
  final int count;

  BeanList({this.list, this.count});
}

abstract class PageProvider<T> {
  Future<BeanList<T>> provide();
}

class IntPageProvider implements PageProvider<int> {
  final size = 5;
  final count = 9;
  int offset = 0;

  List<int> _generateList(int startFrom, int size) {
    List<int> list = [];
    for (int i = startFrom; i < startFrom + size; i++) {
      list.add(i);
    }
    return list;
  }

  @override
  Future<BeanList<int>> provide() async {
    final list = _generateList(offset, size);
    print('provide: $list');
    offset += size;
    return BeanList<int>(list: list, count: count);
  }
}

Stream<T> itemStream<T>(PageProvider<T> provider) async* {
  int total;
  int sent = 0;
  bool done = false;

  while (true) {
    final BeanList<T> beanList = await provider.provide();
    final list = beanList.list;
    final count = beanList.count;
    total = beanList.count;

    print('Got count:$count, list:$list');
    for (final item in list) {
      print('yield $item');
      yield item;
      sent++;
      done = sent == total;
      if (done) break;
    }
    if (done) break;
  }
}

void main() {
  test('Randomly breaking stream', () {
    itemStream(IntPageProvider()).listen(print);
  });
}

预期的输出我应该得到数字 0 到 8,我有时会这样做,但大多数时候测试会在任何随机位置停止。

【问题讨论】:

  • 我无法在纯飞镖环境和颤振测试中重现这一点。两者都有预期的结果。
  • 添加环境信息,如果无论如何它与环境有关。
  • 仅供参考,您可以在一个 break 语句中使用带标签的 break 来打破两个循环:outerLoop: while (true) { .... for (...) ... if (sent == total) break outerLoop; } }。那么你就不需要done 变量和额外的ifbreak

标签: dart stream flutter-test


【解决方案1】:

感谢 Christopher Moore 抽出宝贵时间,我找到了问题所在。

问题在于我如何在测试中使用流。

目前正在这样做。

test('Randomly breaking stream', () {
    itemStream(IntPageProvider()).listen(print);
});

Stream.listen() 在测试中异步运行,没有任何东西可以让测试等待流被完全消耗。所以测试结束,测试中的所有过程突然停止,因此随机停止点。

但是,如果我们对测试进行一些更改。

test('Test waiting for the stream consumption', () async {
    await itemStream(IntPageProvider()).listen(print).asFuture();
});

这可确保在流完全消耗完之前测试不会结束。

我希望这对遇到同样问题的人有所帮助。

【讨论】:

  • 您也可以使用wait itemStream(...).forEach(print);。我建议从不 使用listen,除非您实际使用返回的订阅。否则使用forEach,它会返回一个future,它会在第一个错误时中断,并用那个错误完成返回的future。更安全,更适合错误处理。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-03-20
  • 1970-01-01
  • 2014-02-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-20
相关资源
最近更新 更多