以下 ProviderNotFoundException 被抛出构建 Consumer<ApplicationStateLogin>(dirty):

时间:2021-07-08 01:58:14

标签: flutter

当我运行该应用程序时它可以工作。当我单击该图标时,它会显示 LogInFlow 小部件,但在测试中它不会断言它找到了一个带有 Key('LogInFlow') 的小部件。

==╡ 小部件库的例外情况 ╞================================= ========= 在构建 Consumer(dirty) 时抛出了以下 ProviderNotFoundException: 错误:在此之上找不到正确的提供者 消费者小部件

发生这种情况是因为您使用了不包含提供程序的 BuildContext 你的选择。有几种常见的情况:

  • 您在 main.dart 中添加了一个新的提供程序并执行了热重载。 要修复,请执行热重启。

  • 您尝试读取的提供程序位于不同的路径中。

    提供者是“有范围的”。因此,如果您在路由中插入 provider,则 其他路由将无法访问该提供程序。

  • 您使用了 BuildContext,它是您尝试读取的提供程序的祖先。

    确保消费者在您的 多提供者/提供者。 这通常发生在您创建提供程序并尝试立即读取它时。

相关的导致错误的小部件是: 消费者 file:///C:/Users/calvo/Documents/flutter/projects/freegapp/lib/main.dart:48:5

==╡ FLUTTER TEST FRAMEWORK 引起的异常情况╞================================= ================ 运行测试时抛出以下 TestFailure 对象: 预期:小部件树中正好有一个匹配的节点 实际:_KeyFinder:<带键 [<'LogInFlow'>] 的零小部件(忽略后台小部件)> 其中:表示没有找到,但预期有一个

当抛出异常时,这是堆栈: #4 主要。 (file:///C:/Users/calvo/Documents/flutter/projects/freegapp/test/main_widget_test.dart:25:5) (从包中删除了一帧:stack_trace) ...

这被以下行的测试期望捕获: file:///C:/Users/calvo/Documents/flutter/projects/freegapp/test/main_widget_test.dart 第 25 行 测试描述是: MyStatefulWidget 创建一个默认小部件作为主页

==╡ FLUTTER TEST FRAMEWORK 引起的异常情况╞================================= ================ 抛出了以下消息: 在当前测试运行过程中检测到多个异常(2),并且至少有一个异常 出乎意料。

** main_widget_test.dart **

// The goal of a widget test is to verify that every widget’s UI looks and behaves as expected.//
// To perform an interaction with a widget in your test, use the WidgetTester
// utility that Flutter provides. For example, you can send tap and scroll
// gestures. You can also use WidgetTester to find child widgets in the widget
// tree, read text, and verify that the values of widget properties are correct.

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

import 'package:freegapp/main.dart';

void main() {
  // The WidgetTester allows building and interacting with widgets in a test environment.
  testWidgets('MyStatefulWidget creates a default widget as a homepage',
      (WidgetTester tester) async {
    // Create the widget by telling the tester to build it. Also triggers a frame.
    await tester.pumpWidget(MyApp());
    expect(find.byKey(Key('default')), findsOneWidget);
    // navigationIndexBar starts at 0 so TheMap should be the widget being displayed.
    expect(find.byKey(Key('TheMap')), findsOneWidget);
    // tap on navigationIndexBar 1
    await tester.tap(find.text('icon'));
    // Rebuild the widget after the state has changed.
    await tester.pump();
    expect(find.byKey(Key('LogInFlow')), findsOneWidget);
    await tester.tap(find.text('Map'));
    await tester.pump();
    expect(find.byKey(Key('TheMap')), findsOneWidget);
  });
}

** main.dart **

import 'package:flutter/material.dart';
import 'package:flutter_config/flutter_config.dart';
import 'package:provider/provider.dart';
import 'src/ApplicationStateLogin.dart';
import 'package:freegapp/TheMap.dart';
import 'package:freegapp/src/ApplicationStateLogin.dart';
import 'package:freegapp/src/LogInFlow.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized(); // Required by FlutterConfig
  await FlutterConfig.loadEnvVariables();

  runApp(
    ChangeNotifierProvider(
      create: (context) => ApplicationStateLogin(),
      builder: (context, _) => MyApp(),
    ),
  );
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Freegap',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyStatefulWidget(key: Key('default')),
    );
  }
}

class MyStatefulWidget extends StatefulWidget {
  MyStatefulWidget({Key? key})
      : super(key: key); // Initializes key for subclasses.
  @override
  _MyStatefulWidgetState createState() => _MyStatefulWidgetState();
}

class _MyStatefulWidgetState extends State<MyStatefulWidget> {
  // for bottom navigation bar
  int _selectedIndex = 0;
  // Widget array for bottom navigation bar
  static final List<Widget> _widgetOptions = <Widget>[
    TheMap(key: Key('TheMap')),
    Consumer<ApplicationStateLogin>(
      builder: (context, appState, _) => LogInFlow(
          email: appState.email,
          loginState: appState.loginState,
          startLoginFlow: appState.startLoginFlow,
          verifyEmail: appState.verifyEmail,
          signInWithEmailAndPassword: appState.signInWithEmailAndPassword,
          cancelRegistration: appState.cancelRegistration,
          registerAccount: appState.registerAccount,
          signOut: appState.signOut,
          key: Key('LogInFlow')),
    ),
  ];
  // for bottom navigation bar
  void _onItemTapped(int index) {
    setState(() {
      _selectedIndex = index;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: _widgetOptions.elementAt(_selectedIndex),
      ),
      // body:
      bottomNavigationBar: BottomNavigationBar(
        items: const <BottomNavigationBarItem>[
          BottomNavigationBarItem(
            icon: Icon(Icons.map_outlined),
            label: 'Map',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.home_outlined),
            label: 'icon',
          ),
        ],
        currentIndex: _selectedIndex,
        onTap: _onItemTapped,
      ),
    );
  }
}

1 个答案:

答案 0 :(得分:0)

我想通了。我在测试文件中构建了错误的小部件。我需要构建 ChangeNotifierProvider 小部件并提供适当的包。

    await tester.pumpWidget(ChangeNotifierProvider(
      create: (context) => ApplicationStateFirebase(),
      builder: (context, _) => MyApp(),
    ));

代替

await tester.pumpWidget(MyApp());