rxdart icon indicating copy to clipboard operation
rxdart copied to clipboard

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

Open agavrilko opened this issue 3 years ago • 1 comments

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.

agavrilko avatar Nov 19 '22 21:11 agavrilko

We are running into this issue as well

CaleyD avatar Jul 11 '23 17:07 CaleyD