此单元测试失败的原因是,正如您所解释的,verify
是在流侦听器的异步操作之前执行的.
这些异步操作可能需要一些时间,因此依赖于某种计时器(包括那些处理超时的计时器).想想远程API调用吧.这些操作被放在称为事件队列的东西中,因为它们的完成依赖于发生的一些外部事件.
但它们可能只是一些延迟的、快速完成的操作,称为微任务.它们可能会令人困惑,因为它们看起来像同步操作,而我们可以预期它们会同步完成.它们被放入被称为微任务队列的东西中.
我不知道你的updateToken
执行什么样的异步任务,所以我给你两个解决方案.
我举了这个例子:
import 'package:fake_async/fake_async.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_test/flutter_test.dart';
main() {
test("Sync with timers", () {
int n = 0;
var stream = Stream.fromIterable([1, 2, 3, 4, 5]);
stream.listen((value) async {
await Future.delayed(Duration(seconds: value));
n = value;
debugPrint(value.toString());
});
expect(n, 0);
});
test("Sync with microtasks", () {
int n = 0;
var stream = Stream.fromIterable([1, 2, 3, 4, 5]);
stream.listen((value) async {
n = value;
debugPrint(value.toString());
});
expect(n, 0);
});
test("Fake async with timers", () {
fakeAsync((fa) {
int n = 0;
var stream = Stream.fromIterable([1, 2, 3, 4, 5]);
stream.listen((value) async {
await Future.delayed(Duration(seconds: value));
n = value;
debugPrint(value.toString());
});
fa.flushTimers();
expect(n, 5);
});
});
test("Fake async with microtasks", () {
fakeAsync((fa) {
int n = 0;
var stream = Stream.fromIterable([1, 2, 3, 4, 5]);
stream.listen((value) async {
n = value;
debugPrint(value.toString());
});
fa.flushMicrotasks();
expect(n, 5);
});
});
}
前两个测试显示了我们期望在同步单元测试中发生的事情,就像您所做的那样.在调用expect
之前,n
不会增加.第二个测试最令人惊讶,因为即使我们的"异步"任务实际上是同步的(它只是赋值并打印它),它也只在SYNC语句之后运行,包括expect
.
通过使用fake_async
包,您可以操作事件队列和微任务队列.您的单元测试嵌套在fakeAsync调用中,通过调用flushTimers
或flushMicrotasks
,您可以完成流侦听器的所有异步操作.
请注意,如果将调用切换到flushTimers
和flushMicrotasks
,fakeAsync测试将失败,这表明您需要调用其中的哪一个取决于异步任务的具体性质.