I have the following unit test, which intentionally throws an error.
Note: this is a minimal example and not representative of the actual problem I'm trying to solve.
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
void main() {
testWidgets('future builder ex error', (tester) async {
await tester.pumpWidget(MaterialApp(
home: Scaffold(
body: FutureBuilder<void>(
future: delayedError(),
builder: (context, _) => const Text('hi')))));
await tester.pumpAndSettle(const Duration(seconds: 3));
expect(tester.takeException(), isInstanceOf<Exception>());
});
}
Future<void> delayedError() async {
late final Timer timer;
timer = Timer.periodic(const Duration(seconds: 1), (t) {
timer.cancel();
throw Exception('Something bad happened');
});
}
When I run this code I'm seeing the following output:
═╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following _Exception was thrown running a test:
Exception: Something bad happened
When the exception was thrown, this was the stack:
#0 delayedError.<anonymous closure> (file:///home/bsutton/git/future_builder_ex/test/src/future_builder_ex2_test.dart:23:5)
#8 FakeTimer._fire (package:fake_async/fake_async.dart:323:16)
#9 FakeAsync._fireTimersWhile (package:fake_async/fake_async.dart:244:13)
#10 FakeAsync.elapse (package:fake_async/fake_async.dart:141:5)
#11 AutomatedTestWidgetsFlutterBinding.pump.<anonymous closure> (package:flutter_test/src/binding.dart:1047:28)
#14 TestAsyncUtils.guard (package:flutter_test/src/test_async_utils.dart:71:41)
#15 AutomatedTestWidgetsFlutterBinding.pump (package:flutter_test/src/binding.dart:1043:27)
#16 WidgetTester.pumpAndSettle.<anonymous closure> (package:flutter_test/src/widget_tester.dart:675:23)
#19 TestAsyncUtils.guard (package:flutter_test/src/test_async_utils.dart:71:41)
#20 WidgetTester.pumpAndSettle (package:flutter_test/src/widget_tester.dart:668:27)
#21 main.<anonymous closure> (file:///home/bsutton/git/future_builder_ex/test/src/future_builder_ex2_test.dart:14:18)
<asynchronous suspension>
<asynchronous suspension>
(elided 12 frames from dart:async and package:stack_trace)
The test description was:
future builder ex error
════════════════════════════════════════════════════════════════════════════════════════════════════
Test failed. See exception logs above.
The test description was: future builder ex error
══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following TestFailure was thrown running a test (but after the test had completed):
Expected: <Instance of 'Exception'>
Actual: <null>
Which: is not an instance of 'Exception'
When the exception was thrown, this was the stack:
#0 fail (package:test_api/src/expect/expect.dart:134:31)
#1 _expect (package:test_api/src/expect/expect.dart:129:3)
#2 expect (package:test_api/src/expect/expect.dart:46:3)
#3 expect (package:flutter_test/src/widget_tester.dart:460:16)
#4 main.<anonymous closure> (file:///home/bsutton/git/future_builder_ex/test/src/future_builder_ex2_test.dart:15:5)
<asynchronous suspension>
<asynchronous suspension>
(elided one frame from package:stack_trace)
════════════════════════════════════════════════════════════════════════════════════════════════════
✖ future builder ex error
I think the core of my problem resolves around the second stack trace:
The following TestFailure was thrown running a test (but after the test had completed):
Expected: <Instance of 'Exception'>
Actual: <null>
Which: is not an instance of 'Exception'
I'm guessing that the exception is not being captured by the framework so test.takeException
doesn't see an error.
How do I setup widget unit tests that are intended to check that exceptions are being correctly handled?