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. 💰
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: