rrousselGit / riverpod

A reactive caching and data-binding framework. Riverpod makes working with asynchronous code a breeze.
https://riverpod.dev
MIT License
5.82k stars 888 forks source link

await ref.watch(streamProvider.future); resolves on the first yield #3504

Closed Wizzel1 closed 2 weeks ago

Wizzel1 commented 2 weeks ago

Describe the bug Given the example from the docs:

@riverpod
Stream<List<String>> chat(ChatRef ref) async* {
  // Connect to an API using sockets, and decode the output
  final socket = await Socket.connect('my-api', 4242);
  ref.onDispose(socket.close);

  var allMessages = const <String>[];
  await for (final message in socket.map(utf8.decode)) {
    // A new message has been received. Let's add it to the list of all messages.
    allMessages = [...allMessages, message];
    yield allMessages;
  }
}

calling await ref.watch(chatProvider.future); resolves after the first yield for me. Is this expected?

I am trying to write tests for my stream provider :

    test('should call syncNote', () async {
      // create a listener
      final listener = MockListener<AsyncValue<UploadAnswersResponse>>();
      // listen to the provider and call [listener] whenever its value changes
      container.listen(
        uploadResultsStreamProvider,
        listener.call,
        fireImmediately: true,
      );

      await container.read(uploadResultsStreamProvider.future);

      verify(
        () => myTestRepo.myMethod(userId: user.id),
      ).called(1);
    });

this always fails because the myTestRepo.myMethod call gets called after the first yield.

What am I doing wrong?

Expected behavior I expected the future to resolve after the last yield

rrousselGit commented 2 weeks ago

calling await ref.watch(chatProvider.future); resolves after the first yield for me. Is this expected?

I don't get what this means. Could you expand on what you mean by resoles after the first yield?

Wizzel1 commented 2 weeks ago

calling await ref.watch(chatProvider.future); resolves after the first yield for me. Is this expected?

I don't get what this means. Could you expand on what you mean by resoles after the first yield?

I mean whenever the stream emits its first value(the first message in chatProvider), the future is completed.

I was looking for a way to await the "last" emit in a list of known events.

Someone in the discord channel told me that this is expected: https://discord.com/channels/765557403865186374/765557404766830614/1232636327573327873

I am now using fakeAsync to await the completion of my stream.

rrousselGit commented 2 weeks ago

Yes this is expected. Using .future returns the most recently emitted value.