Ark*_*kan 9 reactive-programming 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();
}
});
Run Code Online (Sandbox Code Playgroud)
我需要测试该成员数据Word::content这是一个String等于在所提供的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;
}));
Run Code Online (Sandbox Code Playgroud)
Kev*_*ore 11
尝试使用async/await和expectLater
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();
}
});
Run Code Online (Sandbox Code Playgroud)
如果您的流正在发出具有您想要测试的属性的对象,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)
);
Run Code Online (Sandbox Code Playgroud)
在上面的示例中,expectAsync1包含一个匿名函数:
(record) {
expect(record.name, expectedRecords[i].name);
i++;
}
Run Code Online (Sandbox Code Playgroud)
Record每次Stream 发出a 时都会运行recordStream
in1是expectAsync1您的封闭函数将采用的参数数量。大多数情况下,这将是 1.(record)是上面的一个参数。
对于上面的示例,expectAsync1具有(可选)类型参数:<void,Record>第二个类型参数Record告诉封闭的函数发出的流项是类型Record,允许我使用类似record.name不进行强制转换的属性。
第一个类型参数是封闭函数的返回类型。我使用它是void因为封闭的函数没有返回任何内容,它只是运行一个expectMatcher 并迭代一个计数器,该计数器用于迭代Record我期望按expectedRecords该顺序看到的列表(即)。
您会注意到max: -1下面包含的函数。这是一个可选但重要的参数,用于expectAsync1指定我们期望的流项目/事件的数量。
1如果max未给出,则默认为如果发出超过 1 个事件,则测试将失败。
错误将是Callback called more times than expected (1).
在上面的示例中,我使用的-1意味着可以发出/测试无限的事件。如果您想测试从流中获取的项目/事件的数量,您可以指定一个非零数字,否则测试将失败。我可以用max: 3上面的例子。
如果您使用 RxDart,BehaviorSubject请记住最近的流事件是在 上发出的listen。因此,在您的测试中,当您开始监听/使用时expectAsync1,将立即调用包含最新事件的封闭函数。
ReplaySubject将在 上发出所有先前的流事件listen。
在阅读dart文件中的源代码并在互联网上阅读后,我找到了解决方案:我需要创建一个自定义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<WordMatcher>(
(Word 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;
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5788 次 |
| 最近记录: |