Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BehaviorSubject doesn't provide value via 'first' in test environment #702

Open
agavrilko opened this issue Nov 19, 2022 · 1 comment
Open
Assignees

Comments

@agavrilko
Copy link

The dartpad example:
https://dartpad.dev/?id=02878d4135fdf329059f95fb9f7a72c4

Description

The issue only appears in widget test environment ('testWidgets').
If widget utilize the 'stream.first' within itself or bloc, not really matters,
and stream is BehaviorSubject, the Future provided by 'first' never finishes.

Example

The widget in the example below just shows text 'Value = $number'
with the number from assigned stream.

In the real environment the last added value to the stream is shown on the screen.
But in the test we see 'Value = -1' because timeout fires.
Without timeout widget never receives any value.

void main() {
  testWidgets('Proof', (tester) async {
    final BehaviorSubject<int> subject = BehaviorSubject.seeded(99);
    final valueFinder = find.text('Value = 99');
    final noneFinder = find.text('None');
    await tester.pumpWidget(
      MaterialApp(
        home: SomeWidget(stream: subject),
      ),
    );
    print('Looking for None');
    expect(valueFinder, findsNothing);
    expect(noneFinder, findsOneWidget);
    await tester.pumpAndSettle();
    print('Looking for Value = 99');
    expect(valueFinder, findsOneWidget);
    expect(noneFinder, findsNothing);
  });
}

class SomeWidget extends StatelessWidget {
  const SomeWidget({Key? key, required this.stream}) : super(key: key);

  final Stream<int> stream;

  @override
  Widget build(BuildContext context) => FutureBuilder<int>(
        future: stream.first
            .timeout(const Duration(milliseconds: 10))
            .onError<TimeoutException>((e, st) => -1),
        builder: (context, snapshot) => Center(
          child: Text(
            snapshot.hasData ? 'Value = ${snapshot.data}' : 'None',
          ),
        ),
      );
}

Note

According to this issue, if we wrap pumpWidget within runAsync, it actually works.
However, it doesn't feel right. It is more like a workaround.

The question is, can this issue be resolved?
If not, or if you believe this is not an issue, could you clarify why such behavior is legit.

Thanks in advance.

@hoc081098 hoc081098 self-assigned this Nov 23, 2022
@CaleyD
Copy link

CaleyD commented Jul 11, 2023

We are running into this issue as well

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants