mockingjay icon indicating copy to clipboard operation
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

Open maheini opened this issue 2 years ago • 6 comments

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:

  1. Create *_test.dart with the content of the Example from the docs (v0.3.0)
  2. 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!

maheini avatar Apr 06 '22 08:04 maheini

I am also experiencing a similar issue.

cornwe19 avatar Apr 25 '22 21:04 cornwe19

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)

Hwan-seok avatar Apr 28 '22 18:04 Hwan-seok

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() {

nickesk avatar May 09 '22 17:05 nickesk

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.

klisiewicz avatar Jun 09 '22 11:06 klisiewicz

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 👍🏻

jeroen-meijer avatar Jun 10 '22 09:06 jeroen-meijer

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

donghyeon avatar Jul 08 '22 16:07 donghyeon