如何在Dart中测试流

时间:2018-08-21 21:30:42

标签: dart

如何在dart中测试流?我有以下代码:

 test('words are reading sequentially correct', () {
    WordTrackerInterface wordTracker = WordTracker.byContent('0 1 2');
    wordTracker.setWordsCountPerChunk(1);
    var stream = wordTracker.nextWordStringStream();

expect(stream, 
      emitsInOrder(List<Word>.generate(6, (i) => i > 2 ? Word('') : Word(i.toString()))));

    for (int i = 0; i < 6; i++) {
      wordTracker.nextWord();
    }
  });

我需要测试成员数据Word :: content(它是一个“字符串”)是否等于“ emitsInOrder”中提供的数据。

类似于以下内容的流

expect(stream, 
          emitsInOrder(List<Word>.generate(6, (i) => i > 2 ? Word('') : Word(i.toString()))), 
expect((Word actual, Word expected) {
  return actual.content == expected.content;
}));

谢谢

3 个答案:

答案 0 :(得分:2)

尝试使用async / awaitexpectLater

test('words are reading sequentially correct', () async {
  WordTrackerInterface wordTracker = WordTracker.byContent('0 1 2');
  wordTracker.setWordsCountPerChunk(1);
  var stream = wordTracker.nextWordStringStream();

  await expectLater(
      stream,
      emitsInOrder(List<Word>.generate(
          6, (i) => i > 2 ? Word('') : Word(i.toString()))));

  for (int i = 0; i < 6; i++) {
    wordTracker.nextWord();
  }
});

答案 1 :(得分:1)

在读取dart文件中的源代码并在Internet上阅读后,我找到了解决方案:我需要创建一个自定义Matcher。我在笔记本电脑上测试了以下代码,并通过引用应用程序中的其他文件(如“ WordTracker”),代码按预期运行。

test('words are reading sequentially correct', () {
    WordTrackerInterface wordTracker = WordTracker.byContent('0 1 2');
    wordTracker.setWordsCountPerChunk(1);
    var stream = wordTracker.nextWordStringStream();

    expect(stream, 
      emitsInOrder(List<Word>.generate(6, (i) => i > 2 ? Word('') : Word(i.toString())).map(
        (value) => WordMatcher(value))));

    for (int i = 0; i < 6; i++) {
      wordTracker.nextWord();
    }
  });


class WordMatcher extends Matcher {
  Word expected;
  Word actual;
  WordMatcher(this.expected);

  @override
  Description describe(Description description) {
    return description.add("has expected word content = '${expected.content}'");
  }

  @override
  Description describeMismatch(
    dynamic item,
    Description mismatchDescription,
    Map<dynamic, dynamic> matchState,
    bool verbose
  ) {
    return mismatchDescription.add("has actual emitted word content = '${matchState['actual'].content}'");
  }

  @override
  bool matches(actual, Map matchState) {
    this.actual = actual;
    matchState['actual'] = actual is Word ? actual : Word('unknown');
    return (actual as Word).content == expected.content;
  }
}

答案 2 :(得分:0)

如果您的流正在发射具有您要测试的属性的对象,expectAsync1可以帮助您:

List<Record> expectedRecords = [record1, record2, record3];
int i = 0;
recordStream.listen(
    expectAsync1<void,Record>(
    (record) {
      expect(record.name, expectedRecords[i].name);
      i++;
    }, 
    max: -1)
);

在上面的示例中,expectAsync1包含一个匿名函数:

    (record) {
      expect(record.name, expectedRecords[i].name);
      i++;
    }

每次由流Record发出recordStream时,就会运行此操作

1中的expectAsync1是封闭函数将采用的参数数量。通常是1。(record)是上面的一个参数。

对于上面的示例,expectAsync1具有(可选)类型参数:<void,Record>第二个类型参数Record告诉封闭的函数,发出的流项目属于Record类型,允许我使用record.name之类的属性而无需强制转换。

第一个类型参数是封闭函数的返回类型。我使用了void,因为封闭的函数没有返回任何内容,它只是运行一个expect Matcher并迭代了一个计数器,该计数器用于迭代我期望的Record的列表依次查看(即expectedRecords)。

Max参数

您会注意到随附功能下方的max: -1。对于expectAsync1,这是一个可选的但重要的参数,用于指定我们期望的流项目/事件的数量。

如果未提供1,则默认为max ;如果大于1,则测试 将失败 事件被发出。

错误将是Callback called more times than expected (1).

在上面的示例中,我使用-1至极,这意味着可以发射/测试无限制的事件。如果要测试,可以指定一个非零数字,以确保从流中准确地获得许多项目/事件,否则测试将失败。我本可以在上面的示例中使用max: 3

RxDart

如果您使用的是RxDart BehaviorSubject,请记住,最新的流事件是在listen上发出的。因此,在您的测试中,当您开始监听/使用expectAsync1时,将立即调用包含最近事件的封闭函数。

ReplaySubject将在listen上发出所有先前的流事件。