Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to restore FlutterError.onError?

In my app, I record the flutter onError to crashalytics,

FlutterError.onError = FirebaseCrashlytics.instance.recordFlutterError;

While running the integration test, if some exceptions happens I get the below statement in the console and the test just hangs,

The following exception was thrown running a test: I/flutter (30479): A test overrode FlutterError.onError but either failed to return it to its original state, or had unexpected additional errors that it could not handle. Typically, this is caused by using expect() before restoring FlutterError.onError.

The above message in console suggests something is wrong with the onError overriding, how do I return FlutterError.onError to its original state as per the recommendation coming up in console.

Please note that I am using the newly recommended way for integration test,

like image 325
MeanMan Avatar asked Apr 28 '21 04:04

MeanMan


People also ask

How do you use onError in flutter?

onError property Null safety Called whenever the Flutter framework catches an error. The default behavior is to call presentError. You can set this to your own function to override this default behavior. For example, you could report all errors to your server.

What is integration testing in flutter?

Integration tests in Flutter are written using the integration test package, provided by the SDK. This is Flutter's version of Selenium WebDriver (generic web), Protractor (Angular), Espresso (Android), or Earl Gray (iOS). The package internally uses flutter driver to drive the test on a device.

How do I ignore errors in flutter?

Deep in the Flutter framework in the file, assertions.dart, you can see what this function does in turn — it calls the FlutterExceptionHandler static function, onError, if any. See that ‘if’ statement? That tells you you could assign null to FlutterError.onError and ignore any Flutter errors.

What is fluttererror onerror and dumperrortoconsole?

Again, by design, the static function, FlutterError.onError, is called whenever the Flutter framework catches an error. Its default behavior is to then call yet another static function, dumpErrorToConsole.

Should Flutter’s onerror function be called before or after the static function?

Yeah, don’t do that. So, to review, you’ll find throughout the Flutter framework that the static function, FlutterError.onError, is called immediately prior to the static function, ErrorWidget.builder, with both using the same ‘exception’ object, FlutterErrorDetails. Again, pretty consistently throughout the framework.

What is error-prone operation in flutter?

An error-prone operation is called. It’s inside a try-catch statement. An error calls a function in the catch clause. A FlutterErrorDetails object is created.


Video Answer


2 Answers

onError is a public static member of FlutterError, so technically it can be overridden by anyone from anywhere. The testWidgets() function itself overrides the FlutterError.onError with its own error handler as well before running the test body. You can read its source code for more info.

Basically, below is what happened:

testWidgets('', (tester) async { // onError is overridden with the handler of the test framework
  await app.main(); // onError is overridden again with crashlytics error handler
  //...
  expect(); // Flutter yells that you should have not touched its onError
});

The point is the Flutter test framework needs its onError to work properly. So whatever you do, remember to call the error handler of the test framework.

Below is the way I used in my project to "restore" the FlutterError.onError (and do something else):

testWidgets('', (tester) async {
  final originalOnError = FlutterError.onError!;
  FlutterError.onError = (FlutterErrorDetails details) {
    // do something like ignoring an exception
    originalOnError(details); // call test framework's error handler
  };
  // ...
  expect();
});

With some modification, I think your problem is solvable.

like image 99
Hieu Pham Avatar answered Oct 30 '22 06:10

Hieu Pham


This helper function I wrote works for me:


Future<void> restoreFlutterError(Future<void> Function() call) async {
  final originalOnError = FlutterError.onError!;
  await call();
  final overriddenOnError = FlutterError.onError!;

  // restore FlutterError.onError
  FlutterError.onError = (FlutterErrorDetails details) {
    if (overriddenOnError != originalOnError) overriddenOnError(details);
    originalOnError(details);
  };
}

void main(){
  testWidgets("some test", (tester) async {
    await restoreFlutterError(() async {
      app.main();
      await tester.pumpAndSettle();
    });
    // ...
    expect(...);
  });
}

Anything that overrides FlutterError.onError can be wrapped around restoreFlutterError - the function makes sure that both onError handler (your and the one set by the test framework) are called.

like image 36
Harsh Bhikadia Avatar answered Oct 30 '22 07:10

Harsh Bhikadia