diff --git a/packages/flutter_test/lib/src/binding.dart b/packages/flutter_test/lib/src/binding.dart index 4e217ffda2..bd36580283 100644 --- a/packages/flutter_test/lib/src/binding.dart +++ b/packages/flutter_test/lib/src/binding.dart @@ -1116,23 +1116,20 @@ class AutomatedTestWidgetsFlutterBinding extends TestWidgetsFlutterBinding { void _verifyInvariants() { super._verifyInvariants(); - assert(() { - if ( _currentFakeAsync.periodicTimerCount == 0 - && _currentFakeAsync.nonPeriodicTimerCount == 0) { - return true; - } - - debugPrint('Pending timers:'); - for (final FakeTimer timer in _currentFakeAsync.pendingTimers) { - debugPrint( - 'Timer (duration: ${timer.duration}, ' - 'periodic: ${timer.isPeriodic}), created:'); - debugPrintStack(stackTrace: timer.creationStackTrace); - debugPrint(''); - } - return false; - }(), 'A Timer is still pending even after the widget tree was disposed.'); - + bool timersPending = false; + if (_currentFakeAsync.periodicTimerCount != 0 || + _currentFakeAsync.nonPeriodicTimerCount != 0) { + debugPrint('Pending timers:'); + for (final FakeTimer timer in _currentFakeAsync.pendingTimers) { + debugPrint( + 'Timer (duration: ${timer.duration}, ' + 'periodic: ${timer.isPeriodic}), created:'); + debugPrintStack(stackTrace: timer.creationStackTrace); + debugPrint(''); + } + timersPending = true; + } + assert(!timersPending, 'A Timer is still pending even after the widget tree was disposed.'); assert(_currentFakeAsync.microtaskCount == 0); // Shouldn't be possible. } diff --git a/packages/flutter_test/test/widget_tester_test.dart b/packages/flutter_test/test/widget_tester_test.dart index e3b1669acb..a48a0f83ae 100644 --- a/packages/flutter_test/test/widget_tester_test.dart +++ b/packages/flutter_test/test/widget_tester_test.dart @@ -775,6 +775,33 @@ void main() { expect(desktop.values.union(mobile.values), equals(all.values)); }); }); + + group('Pending timer', () { + TestExceptionReporter currentExceptionReporter; + setUp(() { + currentExceptionReporter = reportTestException; + }); + + tearDown(() { + reportTestException = currentExceptionReporter; + }); + + test('Throws assertion message without code', () async { + FlutterErrorDetails flutterErrorDetails; + reportTestException = (FlutterErrorDetails details, String testDescription) { + flutterErrorDetails = details; + }; + + final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized() as TestWidgetsFlutterBinding; + await binding.runTest(() async { + final Timer timer = Timer(const Duration(seconds: 1), () {}); + expect(timer.isActive, true); + }, () {}); + + expect(flutterErrorDetails?.exception, isA()); + expect(flutterErrorDetails?.exception?.message, 'A Timer is still pending even after the widget tree was disposed.'); + }); + }); } class FakeMatcher extends AsyncMatcher {