Repository: flutter/flutter
File: packages/flutter/test/widgets/overlay_portal_test.dart (Dart)

Code before:
                      builder: (BuildContext context) {
                        return moveToSecondOverlay
                            ? OverlayPortal(
                              key: portalKey,
                              controller: controller1,
                              overlayChildBuilder: (BuildContext context) => overlayChild,
                              child: child,
                            )
                            : const SizedBox();
                      },
                    ),
                  ],
                ),
              ],
            );
          },
        ),
      ),
    );

    // Move to second overlay
    setState(() {
      moveToSecondOverlay = true;
    });
    await tester.pump();

    verifyTreeIsClean();
  });

  group('GlobalKey Reparenting', () {
    testWidgets('child is laid out before overlay child after OverlayEntry shuffle', (
      WidgetTester tester,
    ) async {
      int layoutCount = 0;

      final GlobalKey widgetKey = GlobalKey(debugLabel: 'widget');
      final RenderBox childBox = RenderConstrainedBox(
        additionalConstraints: const BoxConstraints(),
      );
      final RenderBox overlayChildBox = RenderConstrainedBox(
        additionalConstraints: const BoxConstraints(),
      );
      final OverlayEntry overlayEntry1 = OverlayEntry(
        builder: (BuildContext context) {
          return _ManyRelayoutBoundaries(
            levels: 50,
            child: Builder(
              builder: (BuildContext context) {
                return OverlayPortal(
                  key: widgetKey,
                  controller: controller1,

Review comment (suggestion):
I suspect when the `StatefulBuilder` rebuilds, the builder callback will be called a second time, creating new OverlayEntries so in the test 4 OverlayEntries were created but only 2 were disposed.

Code after:
    moveToSecondOverlay = true;
    overlayEntry1.markNeedsBuild();
    overlayEntry2.markNeedsBuild();
    await tester.pump();

    verifyTreeIsClean();
  });

  group('GlobalKey Reparenting', () {
    testWidgets('child is laid out before overlay child after OverlayEntry shuffle', (
      WidgetTester tester,
    ) async {
      int layoutCount = 0;

      final GlobalKey widgetKey = GlobalKey(debugLabel: 'widget');
      final RenderBox childBox = RenderConstrainedBox(
        additionalConstraints: const BoxConstraints(),
      );
      final RenderBox overlayChildBox = RenderConstrainedBox(
        additionalConstraints: const BoxConstraints(),
      );
      final OverlayEntry overlayEntry1 = OverlayEntry(
        builder: (BuildContext context) {
          return _ManyRelayoutBoundaries(
            levels: 50,
            child: Builder(
              builder: (BuildContext context) {
                return OverlayPortal(
                  key: widgetKey,
                  controller: controller1,
                  overlayChildBuilder: (BuildContext context) {
                    return LayoutBuilder(
                      builder: (BuildContext context, BoxConstraints constraints) {
                        layoutCount += 1;
                        verifyOverlayChildReadyForLayout(widgetKey);
                        return WidgetToRenderBoxAdapter(renderBox: overlayChildBox);
                      },
                    );
                  },
                  child: WidgetToRenderBoxAdapter(renderBox: childBox),
                );
              },
            ),
          );
        },
      );
      addTearDown(
        () =>
            overlayEntry1
              ..remove()
              ..dispose(),