当我运行该应用程序时它可以工作。当我单击该图标时,它会显示 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,
),
);
}
}
答案 0 :(得分:0)
我想通了。我在测试文件中构建了错误的小部件。我需要构建 ChangeNotifierProvider 小部件并提供适当的包。
await tester.pumpWidget(ChangeNotifierProvider(
create: (context) => ApplicationStateFirebase(),
builder: (context, _) => MyApp(),
));
代替
await tester.pumpWidget(MyApp());