flutterdart

How to test assertions in build methods or in callbacks?


I have 2 widgets

1 with an assert in its build method:

class MyWidget1 extends StatelessWidget {
  const MyWidget1({super.key});

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

1 with an assert in a callback of a button:

class MyWidget2 extends StatelessWidget {
  const MyWidget2({super.key});

  @override
  Widget build(BuildContext context) {
    return TextButton(
      onPressed: () {
        assert(false);
      },
      child: const Text('button'),
    );
  }
}

I want a test that verifies the assert is thrown. From this question, I tried:

void main() {
  testWidgets('It should throw an assert error during the build',
      (WidgetTester tester) async {
    await expectLater(
      () => tester.pumpWidget(const MaterialApp(home: MyWidget1())),
      throwsA(isA<AssertionError>()),
    );
  });

  testWidgets('It should throw an assert error on tap',
      (WidgetTester tester) async {
    await tester.pumpWidget(const MaterialApp(
      home: Scaffold(
        body: MyWidget2(),
      ),
    ));
    await expectLater(
      () async {
        await tester.tap(find.byType(TextButton));
        await tester.pumpAndSettle();
      },
      throwsAssertionError,
    );
  });
}

But the errors are not caught by the expects.

How to test it?


Solution

  • You can use FlutterError.onError for that:

    void main() {
      late FlutterExceptionHandler? oldFlutterError;
      setUp(() {
        oldFlutterError = FlutterError.onError;
      });
    
      tearDown(() {
        FlutterError.onError = oldFlutterError;
      });
      testWidgets('It should throw an assert error during the build',
          (WidgetTester tester) async {
        final List<FlutterErrorDetails> errors = <FlutterErrorDetails>[];
        FlutterError.onError = (FlutterErrorDetails details) {
          errors.add(details);
        };
    
        await tester.pumpWidget(const MaterialApp(home: MyWidget1()));
    
        expect(errors, hasLength(1));
        expect(errors.single.exception, isAssertionError);
      });
    
      testWidgets('It should throw an assert error on tap',
          (WidgetTester tester) async {
        final List<FlutterErrorDetails> errors = <FlutterErrorDetails>[];
        FlutterError.onError = (FlutterErrorDetails details) {
          errors.add(details);
        };
        await tester.pumpWidget(const MaterialApp(
          home: Scaffold(
            body: MyWidget2(),
          ),
        ));
        await tester.tap(find.byType(TextButton));
        await tester.pump();
    
        expect(errors, hasLength(1));
        expect(errors.single.exception, isAssertionError);
      });
    }