如何在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;
}));
谢谢
答案 0 :(得分:2)
尝试使用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();
}
});
答案 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: -1
。对于expectAsync1
,这是一个可选的但重要的参数,用于指定我们期望的流项目/事件的数量。
如果未提供1
,则默认为max
;如果大于1,则测试 将失败 事件被发出。
错误将是Callback called more times than expected (1).
在上面的示例中,我使用-1
至极,这意味着可以发射/测试无限制的事件。如果要测试,可以指定一个非零数字,以确保从流中准确地获得许多项目/事件,否则测试将失败。我本可以在上面的示例中使用max: 3
。
如果您使用的是RxDart BehaviorSubject
,请记住,最新的流事件是在listen
上发出的。因此,在您的测试中,当您开始监听/使用expectAsync1
时,将立即调用包含最近事件的封闭函数。
ReplaySubject
将在listen
上发出所有先前的流事件。