matcher
matcher copied to clipboard
Add a Timeout to emits()
I want to test if a Stream doesn't emit anything if a variable is false, I can't see how to do it with the current API, so a timeout of 1 second should be enough and receiving the timeout should be possible to indicate that the test run successfully.
var subscription = someStream.listen((_) {
fail('Should not emit');
});
await Future.delayed(const Duration(seconds: 1));
await subscription.cancel();
Waiting for a value and waiting for a fixed amount of time for no value are sufficiently different that I'd prefer not to mix it in with emits. We could add doesNotEmitFor(Duration), but a test like this feels like a bit of an antipattern and for the edges where we need to do it I think the few extra lines of code aren't too bad. We wouldn't get any value out of the StreamQueue stuff as far as I can tell.
cc @grouma for thoughts.
I like the idea of doesNotEmitFor(Duration). As an alternative you can do something like this today:
test('timeout test', () async {
var completer = Completer();
expect(completer.future.timeout(Duration(seconds: 1)),
throwsA(TypeMatcher<TimeoutException>()));
});
@grouma can your example be used for Stream?
@natebosch yeah, I see your point, it does fill a bit of an antipattern, but at the same time doesNotEmitFor(Duration) sounds useful and not harmful, so why not?
You can use toList() on a Stream to likely get the behavior your want. For example:
test('timeout test', () async {
var controller = StreamController();
expect(controller.stream.toList().timeout(Duration(seconds: 1)),
throwsA(TypeMatcher<TimeoutException>()));
});
@grouma thanks, but for my use case, @natebosch solution was better as I had to call a method to trigger the emission.
Thumbs up for doesNotEmitFor!