dart-lang / leak_tracker

A framework for memory leak tracking for Dart and Flutter applications.
https://pub.dev/packages/leak_tracker
BSD 3-Clause "New" or "Revised" License
396 stars 23 forks source link

StatefulElements are considered "not disposed" if an exception happens in a State lifecycle #221

Closed rrousselGit closed 4 months ago

rrousselGit commented 8 months ago

Hello!

Consider the following test:

import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';

void main() {
  testWidgets('Example', (tester) async {
    await tester.pumpWidget(const MyWidget());

    expect(tester.takeException(), isUnimplementedError);
  });
}

class MyWidget extends StatefulWidget {
  const MyWidget({Key? key}) : super(key: key);

  @override
  State<MyWidget> createState() => _MyWidgetState();
}

class _MyWidgetState extends State<MyWidget> {
  @override
  void initState() {
    super.initState();
    throw UnimplementedError();
  }

  @override
  Widget build(BuildContext context) {
    return const Placeholder();
  }
}

This will fail with:

  Expected: leak free
    Actual: <Instance of 'Leaks'>
     Which: contains leaks:
            # The text is generated by leak_tracker.
            # For leak troubleshooting tips open:
            # https://github.com/dart-lang/leak_tracker/blob/main/doc/TROUBLESHOOT.md
            notDisposed:
              total: 1
              objects:
                StatefulElement:
                  test: Example
                  identityHashCode: 470187304       

I assume the issue is that if an exception happens in initState, State.dispose never gets called.

polina-c commented 4 months ago

Sorry for delay on it. Yes, tests with exceptions do not dispose state. Such tests should be opted out from leak tracking:

testWidgets('async onInit throws FlutterError',
  experimentalLeakTesting: LeakTesting.settings.withIgnoredAll(), // leaking by design because of exception
  (WidgetTester tester) async {
...  
polina-c commented 4 months ago

Documented this: https://github.com/dart-lang/leak_tracker/pull/238 Thanks for flagging!