dart Flutter集成测试-如何忽略`Timer`回调中抛出的异常?

sycxhyv7  于 2023-07-31  发布在  Flutter
关注(0)|答案(1)|浏览(151)

我试图为一个没有很好实现的应用程序编写一个测试,并且在Timer回调中抛出了一个异常。我想在集成测试中忽略这个异常,因为我对这个异常不感兴趣。
这是我遇到的问题的一个最小例子:

import 'dart:async';

import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart';

void main() {
  IntegrationTestWidgetsFlutterBinding.ensureInitialized();

  testWidgets(
    'exception test',
    (tester) async {
      await tester.pumpWidget(
        MaterialApp(
          home: Scaffold(
            body: Center(
              child: Text('Hello, World!'),
            ),
          ),
        ),
      );

      // Let's assume this Timer is created inside the app, and I do not
      // want to change it.
      Timer.periodic(
        const Duration(seconds: 2),
        (_) => throw Exception('thrown on purpose'),
      );

      await Future<void>.delayed(Duration(seconds: 3));
  );
}

字符串
flutter test integration_test/exception_test.dart运行上面的代码可以得到:

══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following _Exception was thrown running a test:
Exception: thrown on purpose

When the exception was thrown, this was the stack:
#0      main.<anonymous closure>.<anonymous closure> (file:///Users/bartek/example_project/integration_test/exception_test.dart:31:16)
#16     _RawReceivePort._handleMessage (dart:isolate-patch/isolate_patch.dart:189:12)
(elided 15 frames from class _Timer, dart:async, and package:stack_trace)

The test description was:
  exception test
════════════════════════════════════════════════════════════════════════════════════════════════════
00:30 +0 -1: exception test [E]
  Test failed. See exception logs above.
  The test description was: exception test


现在,我想忽略这个例外。我试着做了两件事:

但我没有成功
我尝试重置回调(记住在测试结束时恢复它):

void main() {
  IntegrationTestWidgetsFlutterBinding.ensureInitialized();

  testWidgets(
    'exception test',
    (tester) async {
      final oldCallback = FlutterError.onError;
      FlutterError.onError = (details) { /* do nothing on purpose */ };

      await tester.pumpWidget(
        MaterialApp(
          home: Scaffold(
            body: Center(
              child: Text('Hello, World!'),
            ),
          ),
        ),
      );

      Timer.periodic(
        const Duration(seconds: 2),
        (_) => throw Exception('thrown on purpose'),
      );

      await Future<void>.delayed(Duration(seconds: 3));
      FlutterError.onError = oldCallback;
    },
  );
}


但是内部Assert仍然被违反:

'package:flutter_test/src/binding.dart': Failed assertion: line 954 pos 14: '_pendingExceptionDetails != null': 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.
  dart:core                                                                                                              _AssertionError._throwNew
  package:flutter_test/src/binding.dart 954:14                                                                           TestWidgetsFlutterBinding._runTest.handleUncaughtError
  package:flutter_test/src/binding.dart 959:9                                                                            TestWidgetsFlutterBinding._runTest.<fn>


我也试着去做:

FlutterError.onError = (details) {
  tester.takeException();
  oldCallback!(details);
};


但可以理解的是,这给出了原始误差。

ajsxfq5m

ajsxfq5m1#

感谢@ermekk,他把我带到了这篇文章,我能够实现这一点:

import 'dart:async';

import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart';

void main() {
  IntegrationTestWidgetsFlutterBinding.ensureInitialized();

  testWidgets(
    'exception test',
    (tester) async {
      await runZonedGuarded(
        () async {
          final oldCallback = FlutterError.onError;
          FlutterError.onError = (details) {/* do nothing on purpose */};

          await tester.pumpWidget(
            MaterialApp(
              home: Scaffold(
                body: Center(
                  child: Text('Hello, World!'),
                ),
              ),
            ),
          );

          Timer.periodic(
            const Duration(seconds: 2),
            (_) => throw Exception('thrown on purpose'),
          );

          await Future<void>.delayed(Duration(seconds: 3));
          FlutterError.onError = oldCallback;
        },
        (error, stack) {
          print('zone caught error: $error');
        },
      );
    },
  );
}

字符串
这是我一直在寻找的暂时解决方案。当然,它会抑制所有错误,因此要小心,一旦原始异常被修复并且不再引发,就立即删除它。
另外,由于我没有调查的原因,当有一个失败的Assert时,测试永远不会结束,例如。expect(true, false)

相关问题