Writing asynchronous tests with streams can be a challenge.
And if we're not careful, we can end up with a test that "hangs" while waiting for stream values to be emitted.
Here's an example:
test(
'test timeout',
() async {
final controller = StreamController<int>();
// add some values (without closing the controller)
controller.addStream(Stream.fromIterable([1, 2, 3]));
await expectLater(
controller.stream,
emitsInOrder([1, 2, 3, 4]),
);
},
);
The test above will wait and eventually timeout because the stream never emits the last expected value.
TimeoutException after 0:00:30.000000: Test timed out after 30 seconds.
And if we have hundreds or thousands of tests running on CI, a default timeout of 30 seconds can cost us a lot of time and money. 💰
sponsor

Level up your Flutter app’s performance. Get full visibility into your Flutter app’s performance, including crashes, exceptions in Dart, network health, custom traces, and more. Solve your trickiest issues, optimize user journeys, and wow your end users - again and again.
Setting a Custom Timeout
To work around this, we can add a timeout argument:
test(
'test timeout',
() async {
final controller = StreamController<int>();
// add some values (without closing the controller)
controller.addStream(Stream.fromIterable([1, 2, 3]));
await expectLater(
controller.stream,
emitsInOrder([1, 2, 3, 4]),
);
},
// 30 seconds is too long. This is much better:
timeout: const Timeout(Duration(seconds: 1)),
);
In this case, the test will still fail, but it will do so after 1 second.
The @Timeout annotation
But of we have a lot of tests, setting an individual timeout for each test is quite tedious.
Instead, we can define a @Timeout
annotation that will apply to all the tests in the file:
// Note: this has to be on the very first line:
@Timeout(Duration(seconds: 1))
import 'dart:async';
import 'package:flutter_test/flutter_test.dart';
void main() {
test(
'test timeout',
() async {
final controller = StreamController<int>();
// add some values (without closing the controller)
controller.addStream(Stream.fromIterable([1, 2, 3]));
await expectLater(
controller.stream,
emitsInOrder([1, 2, 3, 4]),
);
},
);
}
For more info, read the documentation of the official Dart test package:
Happy coding!
Flutter Foundations Course Now Available
I launched a brand new course that covers testing in great depth, along with other important topics like app architecture, state management, navigation & routing, and much more: