Ruchir
Ruchir

Reputation: 1122

Flutter custom widget test with callback function fails

I've implemented a custom widget for which I'm trying to create test cases. Below is my custom widget. It has one method which is onObserve. So whenever controller detects some data, it calls onObserve method.

class CustomWidget extends StatefulWidget {
  final ValueChanged<Model>? onObserve;

  const CustomWidget({super.key, required this.onObserve});

  @override
  State<CustomWidget> createState() => _CustomWidgetState();
}
class _CustomWidgetState extends State<CustomWidget> {
  @override
  Widget build(BuildContext context) {
    MyController mController = MyController();

    return Stack(
      children: [
        Center(
          child: SizedBox(
            width: 350,
            height: 350,
            child: MyObserver(
                controller: mController,
                onDetect: (code, args) {
                  if (code.value != null) {
                      //...TODO
                      widget.onObserve!(myObservedData);
                  }
                }),
          ),
        ),
      ],
    );
  }
}

Below is my test case :

testWidgets('on observe', (WidgetTester tester) async {
    var mModel = Model();

    await tester.pumpWidget(MyWrapper(Scaffold(body: CustomWidget(
      onObserve: (value) {
        value.address = '5, ABC-123';
        mModel = value;
      },
    ))));
    await tester.pumpAndSettle();
    expect(find.byType(CustomWidget), findsOneWidget);
    expect(find.byType(MyObserver), findsOneWidget);
    expect(mModel.address, '5, ABC-123');
    await tester.pumpAndSettle();
  });

This test case is failing always because it's not going into onObserve method. What I'm trying to do is setting data in onObserve method and verifying with expect(mModel.address, '5, ABC-123'); which is always failing. Is there anything wrong with above test ?

Upvotes: 0

Views: 517

Answers (1)

manhtuan21
manhtuan21

Reputation: 3455

If I understand correctly, onDetect of your MyObserve will only be triggered if something happen

await tester.pumpWidget(MyWrapper(Scaffold(body: CustomWidget(
      onObserve: (value) {
        value.address = '5, ABC-123';
        mModel = value;
      },
    ))));
await tester.pumpAndSettle();

Above section of your code only await for your CustomWidget build done, it doesn't wait for onDetect to be triggered, so code inside onObserve will not be called I don't know excalty your MyObserve do, so I fake this example, you can follow it:

testWidgets('on observe', (WidgetTester tester) async {
    var mModel;
    await tester.pumpWidget(MyWrapper(
      home: Scaffold(body: CustomWidget(
        onObserve: (value) {
          mModel = value;
        },
      )),
    ));

    // You maybe need to implement code to trigger your MyObserve class here
    final CustomWidgetState customWidgetState = tester.state(find.byType(CustomWidget));
    customWidgetState.triggerOnDetect();

    await tester.pumpAndSettle();
    expect(find.byType(CustomWidget), findsOneWidget);
    expect(mModel, 123);
  }); 

Upvotes: 1

Related Questions