首页 > 解决方案 > 构建消费者时抛出了以下 ProviderNotFoundException(肮脏的):

问题描述

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

theftion trible tribrars捕获的例外╞═════════════════════════════════════════ ══════ 在构建 Consumer(dirty) 时抛出以下 ProviderNotFoundException:错误:在此 Consumer Widget 上方找不到正确的 Provider

发生这种情况是因为您使用了BuildContext不包括您选择的提供者的 。有几种常见的场景:

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

══╡颤抖测试框架捕获的例外╞════════════════════════════════════════ ════════════ 运行测试时抛出以下 TestFailure 对象: 预期:小部件树中恰好有一个匹配节点 实际:_KeyFinder:<零个带有键 [<'LogInFlow'>] 的小部件(忽略后台小部件)> 其中:表示没有找到,但应该有一个

抛出异常时,这是堆栈:#4 main。(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 创建一个默认小部件为主页

══╡颤抖测试框架捕获的例外╞════════════════════════════════════════ ════════════ 抛出以下信息:当前测试运行过程中检测到多个异常(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,
      ),
    );
  }
}

标签: flutter

解决方案


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

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

代替

await tester.pumpWidget(MyApp());

推荐阅读