Closed mugbug closed 2 years ago
You have to listen mockBar.stream
in your test and then call verify
and expected
inside the listen
callback:
void main() {
final StreamController<int> controllerMock = StreamController<int>();
final mockBar = MockBar();
final mockEventTracker = MockEventTracker();
final values = [7, 3, 2, 5];
late Foo foo;
setUp(() {
when(
() => mockBar.stream,
).thenAnswer((_) => Stream<int>.fromIterable(values));
foo = Foo(bar: mockBar, tracker: mockEventTracker);
});
test('should record all events sent by stream', () {
int index = 0;
mockBar.stream.listen((event) {
expect(event, values[index]);
verify(
() => mockEventTracker.recordEvent(event),
).called(1);
index++;
});
});
}
[SOLVED]
Ok, so I was able to solve this in a reasonable way: basically, it seems the problem was related to asynchronicity. When verify
was called, the stream didn't have finished emitting all events. So to make it wait so all events were emitted before verifying the calls, I implemented this method:
Future<void> waitForStreamToComplete(Stream stream) {
final complete = Completer<void>();
stream.listen((event) {}).onDone(() {
complete.complete();
});
return complete.future;
}
which can be called before the verify
:
test('should record all events sent by the stream', () async {
// make sure the stream is done emitting events
await waitForStreamToComplete(mockBar.stream);
// proceed with the test assertions
final captured = verify(
() => mockEventTracker.recordEvent(captureAny()),
).captured; // returns [7, 3, 2, 5]
// all expectations should be satisfied
expect(captured[0], 7);
expect(captured[1], 3);
expect(captured[2], 2);
expect(captured[3], 5);
});
Let's say I have the following implementation:
And I want to test if when
Bar
's stream emits some events afterFoo
is instantiated, all of those are recorded on aEventTracker
.Here's what I currently have, that works just for the first event:
Am I mocking this in the correct way? Any idea why only the first event is emitted/captured?