我想在我的项目中为提供者(ChangeNotifierProvider
)创建一个单元测试,我的单元测试,窗口小部件测试和集成测试成功通过✔️,所以现在我尝试了(尝试?...)为提供者创建一个单元测试。我可以检查上下文,但是在检查提供程序的初始值(必须为0)时,出现此异常❌:
══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following ProviderNotFoundError was thrown running a test:
Error: Could not find the correct Provider<Counter> above this ChangeNotifierProvider<Counter>
Widget
To fix, please:
* Ensure the Provider<Counter> is an ancestor to this ChangeNotifierProvider<Counter> Widget
* Provide types to Provider<Counter>
* Provide types to Consumer<Counter>
* Provide types to Provider.of<Counter>()
* Always use package imports. Ex: `import 'package:my_app/my_code.dart';
* Ensure the correct `context` is being used.
If none of these solutions work, please file a bug at:
https://github.com/rrousselGit/provider/issues
When the exception was thrown, this was the stack:
#0 Provider.of (package:provider/src/provider.dart:264:7)
#1 main.<anonymous closure>.<anonymous closure> (file:///home/chinnonsantos/FlutterProjects/full_testing_flutter/test/unit/provider_test.dart:33:23)
<asynchronous suspension>
#2 testWidgets.<anonymous closure>.<anonymous closure> (package:flutter_test/src/widget_tester.dart:119:25)
<asynchronous suspension>
#3 TestWidgetsFlutterBinding._runTestBody (package:flutter_test/src/binding.dart:648:19)
<asynchronous suspension>
#6 TestWidgetsFlutterBinding._runTest (package:flutter_test/src/binding.dart:631:14)
#7 AutomatedTestWidgetsFlutterBinding.runTest.<anonymous closure> (package:flutter_test/src/binding.dart:1016:24)
#13 AutomatedTestWidgetsFlutterBinding.runTest (package:flutter_test/src/binding.dart:1013:15)
#14 testWidgets.<anonymous closure> (package:flutter_test/src/widget_tester.dart:116:22)
#15 Declarer.test.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/declarer.dart:168:27)
<asynchronous suspension>
#16 Invoker.waitForOutstandingCallbacks.<anonymous closure> (package:test_api/src/backend/invoker.dart:250:15)
<asynchronous suspension>
#21 Invoker.waitForOutstandingCallbacks (package:test_api/src/backend/invoker.dart:247:5)
#22 Declarer.test.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/declarer.dart:166:33)
#27 Declarer.test.<anonymous closure> (package:test_api/src/backend/declarer.dart:165:13)
<asynchronous suspension>
#28 Invoker._onRun.<anonymous closure>.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/invoker.dart:400:25)
<asynchronous suspension>
#42 _Timer._runTimers (dart:isolate-patch/timer_impl.dart:382:19)
#43 _Timer._handleMessage (dart:isolate-patch/timer_impl.dart:416:5)
#44 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:172:12)
(elided 28 frames from class _FakeAsync, package dart:async, package dart:async-patch, and package stack_trace)
The test description was:
Update when the value changes
════════════════════════════════════════════════════════════════════════════════════════════════════
00:03 +0 -1: [Provider] Update when the value changes [E]
Test failed. See exception logs above.
The test description was: Update when the value changes
00:03 +0 -1: Some tests failed.
Collecting coverage information...
按照我的代码:
-pubspec.yaml
:
...
dependencies:
flutter:
sdk: flutter
test: ^1.6.3
provider: ^3.2.0
dev_dependencies:
flutter_test:
sdk: flutter
flutter_driver:
sdk: flutter
pedantic: ^1.8.0+1
...
lib/main.dart
:import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:full_testing_flutter/counter.dart';
void main() {
runApp(
ChangeNotifierProvider(
create: (context) => Counter(),
child: MyApp(),
),
);
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatelessWidget {
final String title;
MyHomePage({this.title});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Consumer<Counter>(
builder: (context, counter, child) => Text(
'${counter.value}',
key: Key('counter'),
style: Theme.of(context).textTheme.display1,
),
),
],
),
),
floatingActionButton: FloatingActionButton(
key: Key('increment'),
onPressed: () =>
Provider.of<Counter>(context, listen: false).increment(),
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
lib/counter.dart
:import 'package:flutter/foundation.dart';
class Counter with ChangeNotifier {
int value = 0;
void increment() {
value++;
// print('Value++: $value');
notifyListeners();
}
void decrement() {
value--;
// print('Value--: $value');
notifyListeners();
}
}
test/unit/provider_test.dart
:import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:provider/provider.dart';
import 'package:full_testing_flutter/main.dart';
import 'package:full_testing_flutter/counter.dart';
void main() async {
Counter _counterModel;
setUp(() {
_counterModel = Counter();
});
group('[Provider]', () {
testWidgets('Update when the value changes', (tester) async {
final _providerKey = GlobalKey();
BuildContext context;
await tester.pumpWidget(ChangeNotifierProvider<Counter>(
key: _providerKey,
create: (c) {
context = c;
return Counter();
},
child: MyApp(),
));
// Check the context test...
expect(context, equals(_providerKey.currentContext));
// Check the initial value provider 0...
expect(Provider.of<Counter>(_providerKey.currentContext).value, 0);
// // Increment value...
// Provider.of<Counter>(_providerKey.currentContext).increment();
// // Delay the pump...
// await Future.microtask(tester.pump);
// // Check if incremented value is the same as received...
// expect(
// Consumer<Counter>(
// builder: (context, counter, child) => Text('${counter.value}'),
// ),
// _counterModel.value,
// );
// // Decrement value...
// Provider.of<Counter>(context, listen: false).decrement();
// // Delay the pump...
// await Future.microtask(tester.pump);
// // Check if decremented value is the same as received...
// expect(
// Provider.of<Counter>(_childKey.currentContext).value,
// _counterModel.value,
// );
});
});
}
test/unit/counter_test.dart
,test/widget/widget_test.dart
和test_driver/app_test.dart
:
现在这并不重要,但是如果您想看到它,可以在full_testing_flutter (public project)存储库中找到
我可以做些什么来测试提供者(隔离)?我的代码中的错误在哪里?
我从Dart / Flutter(尤其是Provider软件包)开始,有人可以帮助我吗? ?
注意:我的应用程序运行正常,只有针对提供程序的单元测试(我现在正在实现的功能)不起作用!!!
谢谢
答案 0 :(得分:1)
发生此问题的原因是,您正在使用要获取的提供者的BuildContext
来呼叫Provider.of
:
Provider<T>(
key: myKey,
...
)
Provider.of<T>(myKey.currentContext);
这是不可能的,只有该提供者的后代可以呼叫Provider.of
。
考虑将您的测试更改为以下内容:
testWidget('Provider.of', (tester) async {
await tester.pumpWidget(
Provider(
create: (_) => 42,
child: Container(),
),
);
final context = tester.element(find.byType(Container));
expect(Provider.of<int>(context), equals(42));
});