我正在尝试为使用 StreamBuilder
的小部件编写小部件测试。在构建器中,如果 snapshot.hasData
为 false
,则返回 CircularProgressIndicator
,否则返回小部件的 ListView
.
在我的测试中,我创建了一个 StreamController
并向其中添加了一个元素。当我运行测试时,我希望看到 snapshot.hasData
= true
,但它是 false
,我可以看到 >connectionState
是 waiting
。所以我的测试失败了。
不知何故,第一个元素似乎没有从流中拉出,并且连接保持在 waiting
状态。我不确定我做错了什么。
这是我的小部件测试:
testWidgets('Job item pressed - shows edit job page',
(WidgetTester tester) async {
StreamController<List<Job>> controller =
StreamController<List<Job>>.broadcast(sync: true);
Job job = Job(id: '0', createdAt: 0, jobName: 'Dart');
controller.add([job]);
final page = JobsPage(
jobsStream: controller.stream,
);
MockRouter mockRouter = MockRouter();
await tester.pumpWidget(makeTestableWidget(
child: page,
auth: MockAuth(),
database: MockDatabase(),
router: mockRouter,
));
Finder waiting = find.byType(CircularProgressIndicator);
expect(waiting, findsNothing);
Finder placeholder = find.byType(PlaceholderContent);
expect(placeholder, findsNothing);
Finder item = find.byKey(Key('jobListItem-${job.id}'));
expect(item, findsOneWidget);
await controller.close();
});
这是我的小部件代码:
Widget _buildContent(BuildContext context) {
return StreamBuilder<List<Job>>(
stream: jobsStream,
builder: (context, snapshot) {
return ListItemsBuilder(
snapshot: snapshot,
itemBuilder: (BuildContext context, Job job) {
return JobListItem(
key: Key('jobListItem-${job.id}'),
title: job.jobName, // TODO: This be null?
onTap: () => _select(context, job),
);
},
);
},
);
}
还有ListItemsBuilder
:
typedef Widget ItemWidgetBuilder<T>(BuildContext context, T item);
class ListItemsBuilder<T> extends StatelessWidget {
ListItemsBuilder({this.snapshot, this.itemBuilder});
final AsyncSnapshot<List<T>> snapshot;
final ItemWidgetBuilder<T> itemBuilder;
@override
Widget build(BuildContext context) {
// prints "waiting"
print('${snapshot.connectionState.toString()}');
if (snapshot.hasData) {
final items = snapshot.data;
if (items.length > 0) {
return _buildList(items);
} else {
return PlaceholderContent();
}
} else if (snapshot.error != null) {
print('${snapshot.error}');
return PlaceholderContent(
title: 'Something went wrong',
message: 'Can\'t load entries right now',
);
} else {
return Center(child: CircularProgressIndicator());
}
}
Widget _buildList(List<T> items) {
return ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
return itemBuilder(context, items[index]);
},
);
}
}
我尝试使用 StreamController.broadcast(sync: true)
而不是简单的 StreamController
,但没有任何区别。
此外,任何额外的 pump()
和 pumpAndSettle()
调用都不会产生影响。
有什么想法吗?
最佳答案
解决方案
使用 await tester.pump(Duration.zero);
完整的测试代码:
testWidgets('Job item pressed - shows edit job page',
(WidgetTester tester) async {
StreamController<List<Job>> controller = StreamController<List<Job>>();
Job job = Job(id: '0', createdAt: 0, jobName: 'Dart');
controller.add([job]);
final page = JobsPage(
jobsStream: controller.stream,
);
MockRouter mockRouter = MockRouter();
await tester.pumpWidget(makeTestableWidget(
child: page,
auth: MockAuth(),
database: MockDatabase(),
router: mockRouter,
));
// this will cause the stream to emit the first event
await tester.pump(Duration.zero);
Finder waiting = find.byType(CircularProgressIndicator);
expect(waiting, findsNothing);
Finder placeholder = find.byType(PlaceholderContent);
expect(placeholder, findsNothing);
Finder item = find.byKey(Key('jobListItem-${job.id}'));
expect(item, findsOneWidget);
await controller.close();
});
关于dart - Flutter 小部件测试 : StreamBuilder snapshot has connectionState = waiting with a non-empty Stream,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51786850/