mockingjay
mockingjay copied to clipboard
How is the Example supposed to work? I get a "type Null is not a subtype of type Future<dynamic>" error
Description
I tried to use Mockingjay and used it according to the example, but all my tests failed. Well then, I copied the whole example into a new smalltest_test.dart file - but even the example fails.
Steps to reproduce the behavior:
- Create *_test.dart with the content of the Example from the docs (v0.3.0)
- Run the test - it will fail...
Expected:
I expected the example to be failsave... am I missing something?
Additional content
Error message from Flutter Test
00:04 +0: pushes SettingsPage when TextButton is tapped
══╡ EXCEPTION CAUGHT BY GESTURE ╞═══════════════════════════════════════════════════════════════════
The following _TypeError was thrown while handling a gesture:
type 'Null' is not a subtype of type 'Future<dynamic>'
When the exception was thrown, this was the stack:
#0 MockNavigator.push (package:flutter/src/widgets/navigator.dart:4364:14)
#1 _MockNavigatorState.push (package:mockingjay/src/mock_navigator.dart:80:23)
#2 MyHomePage.build.<anonymous closure> (file:///C:/Users/Username/Documents/CarbPro/test/smalltest_test.dart:12:48)
#3 _InkResponseState._handleTap (package:flutter/src/material/ink_well.dart:989:21)
#4 GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:198:24)
#5 TapGestureRecognizer.handleTapUp (package:flutter/src/gestures/tap.dart:608:11)
#6 BaseTapGestureRecognizer._checkUp (package:flutter/src/gestures/tap.dart:296:5)
#7 BaseTapGestureRecognizer.handlePrimaryPointer (package:flutter/src/gestures/tap.dart:230:7)
#8 PrimaryPointerGestureRecognizer.handleEvent (package:flutter/src/gestures/recognizer.dart:563:9)
#9 PointerRouter._dispatch (package:flutter/src/gestures/pointer_router.dart:94:12)
#10 PointerRouter._dispatchEventToRoutes.<anonymous closure> (package:flutter/src/gestures/pointer_router.dart:139:9)
#11 _LinkedHashMapMixin.forEach (dart:collection-patch/compact_hash.dart:539:8)
#12 PointerRouter._dispatchEventToRoutes (package:flutter/src/gestures/pointer_router.dart:137:18)
#13 PointerRouter.route (package:flutter/src/gestures/pointer_router.dart:123:7)
#14 GestureBinding.handleEvent (package:flutter/src/gestures/binding.dart:439:19)
#15 GestureBinding.dispatchEvent (package:flutter/src/gestures/binding.dart:419:22)
#16 RendererBinding.dispatchEvent (package:flutter/src/rendering/binding.dart:322:11)
#17 GestureBinding._handlePointerEventImmediately (package:flutter/src/gestures/binding.dart:374:7)
#18 GestureBinding.handlePointerEvent (package:flutter/src/gestures/binding.dart:338:5)
#19 TestWidgetsFlutterBinding.handlePointerEventForSource.<anonymous closure> (package:flutter_test/src/binding.dart:496:42)
#20 TestWidgetsFlutterBinding.withPointerEventSource (package:flutter_test/src/binding.dart:506:11)
#21 TestWidgetsFlutterBinding.handlePointerEventForSource (package:flutter_test/src/binding.dart:496:5)
#22 WidgetTester.sendEventToBinding.<anonymous closure> (package:flutter_test/src/widget_tester.dart:808:15)
#23 WidgetTester.sendEventToBinding.<anonymous closure> (package:flutter_test/src/widget_tester.dart:807:39)
#26 TestAsyncUtils.guard (package:flutter_test/src/test_async_utils.dart:71:41)
#27 WidgetTester.sendEventToBinding (package:flutter_test/src/widget_tester.dart:807:27)
#28 TestGesture.up.<anonymous closure> (package:flutter_test/src/test_pointer.dart:394:24)
#29 TestGesture.up.<anonymous closure> (package:flutter_test/src/test_pointer.dart:392:39)
#32 TestAsyncUtils.guard (package:flutter_test/src/test_async_utils.dart:71:41)
#33 TestGesture.up (package:flutter_test/src/test_pointer.dart:392:27)
#34 WidgetController.tapAt.<anonymous closure> (package:flutter_test/src/controller.dart:280:21)
<asynchronous suspension>
<asynchronous suspension>
(elided 5 frames from dart:async and package:stack_trace)
Handler: "onTap"
Recognizer:
TapGestureRecognizer#fe552
════════════════════════════════════════════════════════════════════════════════════════════════════
══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following TestFailure was thrown running a test:
No matching calls. All calls:
MockNavigator.push<dynamic>(MaterialPageRoute<dynamic>(RouteSettings("/settings", null), animation:
null))
(If you called `verify(...).called(0);`, please instead use `verifyNever(...);`.)
When the exception was thrown, this was the stack:
#0 fail (package:test_api/src/expect/expect.dart:137:31)
#1 _VerifyCall._checkWith (package:mocktail/src/mocktail.dart:722:7)
#2 _makeVerify.<anonymous closure> (package:mocktail/src/mocktail.dart:515:18)
#3 main.<anonymous closure> (file:///C:/Users/Username/Documents/CarbPro/test/smalltest_test.dart:51:11)
<asynchronous suspension>
<asynchronous suspension>
(elided one frame from package:stack_trace)
The test description was:
pushes SettingsPage when TextButton is tapped
════════════════════════════════════════════════════════════════════════════════════════════════════
══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following message was thrown:
Multiple exceptions (2) were detected during the running of the current test, and at least one was
unexpected.
════════════════════════════════════════════════════════════════════════════════════════════════════
00:04 +0 -1: pushes SettingsPage when TextButton is tapped [E]
Test failed. See exception logs above.
The test description was: pushes SettingsPage when TextButton is tapped
00:04 +0 -1: Some tests failed.
Test code (1:1 the example code)
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockingjay/mockingjay.dart';
class MyHomePage extends StatelessWidget {
const MyHomePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: TextButton(
onPressed: () => Navigator.of(context).push(MySettingsPage.route()),
child: const Text('Navigate'),
),
);
}
}
class MySettingsPage extends StatelessWidget {
const MySettingsPage({Key? key}) : super(key: key);
static Route route() {
return MaterialPageRoute(
builder: (_) => const MySettingsPage(),
settings: const RouteSettings(name: '/settings'),
);
}
@override
Widget build(BuildContext context) {
return const Scaffold();
}
}
void main() {
testWidgets('pushes SettingsPage when TextButton is tapped', (tester) async {
final navigator = MockNavigator();
when(() => navigator.push(any())).thenAnswer((_) async {});
await tester.pumpWidget(
MaterialApp(
home: MockNavigatorProvider(
navigator: navigator,
child: const MyHomePage(),
),
),
);
await tester.tap(find.byType(TextButton));
verify(
() => navigator
.push(any(that: isRoute<void>(whereName: equals('/settings')))),
).called(1);
});
}
Flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[√] Flutter (Channel stable, 2.10.2, on Microsoft Windows [Version 10.0.22000.556], locale de-CH)
[√] Android toolchain - develop for Android devices (Android SDK version 32.0.0)
[√] Chrome - develop for the web
[√] Visual Studio - develop for Windows (Visual Studio Community 2022 17.0.5)
[√] Android Studio (version 2021.1)
[√] VS Code (version 1.66.0)
[√] Connected device (4 available)
[√] HTTP Host Availability
• No issues found!
I am also experiencing a similar issue.
sorry for the annoying alarm but so am I..
The following _TypeError was thrown running a test:
type 'Null' is not a subtype of type 'Future<Object?>'
When the exception was thrown, this was the stack:
#0 MockNavigator.pushNamed (package:flutter/src/widgets/navigator.dart:4094:14)
#1 _MockNavigatorState.pushNamed (package:mockingjay/src/mock_navigator.dart:88:23)
I'm getting the same error as well, though I did have to change line 22 to get this to run:
static Route<void> route() {
I was able to run the example by explicitly adding types. That means I changed the source code from:
onPressed: () => Navigator.of(context).push(MySettingsPage.route()),
to:
onPressed: () => Navigator.of(context).push<void>(MySettingsPage.route()),
static Route route() {
return MaterialPageRoute(
builder: (_) => const MySettingsPage(),
settings: const RouteSettings(name: '/settings'),
);
}
to:
static Route<void> route() {
return MaterialPageRoute<void>(
builder: (_) => const MySettingsPage(),
settings: const RouteSettings(name: '/settings'),
);
}
As well as the tests:
when(() => navigator.push(any())).thenAnswer((_) async {});
to:
when(() => navigator.push<void>(any())).thenAnswer((_) async {});
and finally the assertion:
verify(() => navigator.push(any(that: isRoute<void>(whereName: equals('/settings'))))).called(1);
to:
verify(() => navigator.push<void>(any<Route<void>>(that: isRoute<void>(whereName: equals('/settings'))))).called(1);
I hope this helps.
Hey there,
Thank you all for flagging this! I'll look at this later today. If the solution is simple, expect a fix today as well 👍🏻
The test will pass when changing to the previous versions. mocktail v0.2.0 mockingjay v0.2.0
There is a change related to this issue in the mocktail v0.3.0 update.
- BREAKING feat: add support for type argument matching https://github.com/felangel/mocktail/issues/66#issue-962024992