5

This method will call the init function inside the stateless widget. But how to emulate the call to dispose function?

    var widget = StatelessWidgetExample();
    await tester.pumpWidget(widget);

I also tried to emulate the removal from the tree.

    await tester.pumpWidget(widget);
    await tester.pumpWidget(Container());

but it didn't work

4 Answers 4

3

This worked for me and is relatively simple.

var widget = StatelessWidgetExample();

await tester.pumpWidget(widget);
await tester.pumpAndSettle();
await tester.pumpWidget(Container());
await tester.pumpAndSettle();
Sign up to request clarification or add additional context in comments.

Comments

1

You could use a StreamBuilder and replace YourWidget with another widget, then the dispose method for YourWidget is called.

void main() {
  late StreamController<Widget> widgetStreamController;

  setUp(() async {
    widgetStreamController = StreamController<Widget>();
  });

  tearDown(() async {
    await widgetStreamController.close();
  });

  Widget buildApp() {
    return MaterialApp(
      home: StreamBuilder<Widget>(
        stream: widgetStreamController.stream,
        builder: (context, snapshot) {
          return snapshot.data ?? Container();
        },
      ),
    );
  }

  testWidgets('dispose widget', (tester) async {
    await tester.pumpWidget(buildApp());
    await tester.pumpAndSettle();

    widgetStreamController.add(YourWidget());
    await tester.pumpAndSettle();

    // todo: check here if YourWidget is displayed

    widgetStreamController.add(AnotherWidget());
    await tester.pumpAndSettle();

    // todo: check here if dispose was called 
  });
}

Comments

0

Did it like this


    var key2 = Key('a');
    var testStateful = _TestStateful(
      key: key2,
      child: TestInitDispose(),
    );

    await tester.pumpWidget(testStateful);
    /// will call init

    var state = tester.firstState<__TestStatefulState>(find.byKey(key2));
    state.remove();

    await tester.pump();
    /// will call dispose
  });

...

class _TestStateful extends StatefulWidget {
  final Widget child;
  const _TestStateful({Key? key, required this.child}) : super(key: key);

  @override
  __TestStatefulState createState() => __TestStatefulState();
}

class __TestStatefulState extends State<_TestStateful> {
  bool showChild = true;
  void remove() {
    setState(() {
      showChild = false;
    });
  }

  @override
  Widget build(BuildContext context) {
    return showChild ? widget.child : Container();
  }
}

1 Comment

Thanks for answer and can you help me with dropdown design [How to customize Dropdown Button and items in flutter?][stackoverflow.com/questions/71021122/…
0

You could use a StatefulBuilder to manipulate a flag to show/hide any other widget.

testWidgets(
  'dispose simulation',
  (tester) async {
    var showTestableWidget = true;
    await tester.pumpWidget(
      StatefulBuilder(
        builder: (context, setState) => Column(
          children: [
            ElevatedButton(
              onPressed: () {
                setState(
                  () => showTestableWidget = !showTestableWidget,
                );
              },
              child: const Text('toggle testable widget visibility'),
            ),
            if (showTestableWidget)
              const TestableWidget()
            else
              const SizedBox.shrink(),
          ],
        ),
      ),
    );
    expect(find.byType(TestableWidget), findsOneWidget);
    await tester.tap(find.byType(ElevatedButton));
    await tester.pumpAndSettle();
    expect(find.byType(TestableWidget), findsNothing);
  },
);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.