我想使用Provider将依赖项注入Flutter应用程序中。
我注入了一个调用异步本机方法的“存储库”类。
出于测试目的,我想注入存储库的模拟版本。
这是怎么做到的?
在应用程序代码中:
void main() {
runApp(
MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => Repository()),
],
child: MyApp(),
),
);
}
在测试中:
await tester.pumpWidget(
MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => Repository()),
],
child: MyApp(),
));
虽然应用程序运行良好,但测试失败,并显示与我省略提供程序并仅致电
时相同的消息 tester.pumpWidget(MyApp());
例外是:
在构建MyHomePage(脏状态时,抛出了以下ProviderNotFoundException: _MyHomePageState#9407e): 错误:在此MyHomePage小部件上方找不到正确的提供程序 ...
main.dart:
import 'package:flutter/material.dart';
import 'repository.dart';
import 'package:provider/provider.dart';
void main() {
runApp(
MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => Repository()),
],
child: MyApp(),
),
);
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Demo'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
String _days = "0";
@override
Widget build(BuildContext buildContext) {
final _daysFuture = context.watch<Repository>().daysInSummer();
return Material(
child: FutureBuilder(
future: _daysFuture,
builder: (context, snapshot) {
if (snapshot.hasData) {
_days = snapshot.data;
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'demo text',
),
Text(
"$_days",
style: Theme.of(context).textTheme.headline2,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
context.read<Repository>().addDayInSummer();
},
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
} else {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: [
Text('Waiting for initialisation'),
SizedBox(
height: 16,
),
CircularProgressIndicator(),
],
);
}
}));
}
}
widget_test.dart:
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:provider/provider.dart';
import 'package:summer/main.dart';
class Repository with ChangeNotifier {
int days = 0;
@override
Future<String> addDayInSummer() {
days++;
notifyListeners();
return daysInSummer();
}
@override
Future<String> daysInSummer() {
Future<String> s = Future.delayed(
Duration(milliseconds: 2),
() => days.toString(),
);
notifyListeners();
return s;
}
}
void main() {
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
await tester.pumpWidget(MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => Repository()),
],
child: MyApp(),
));
// Verify that our counter starts at 0.
expect(find.text('0/90'), findsOneWidget);
expect(find.text('1/90'), findsNothing);
//Tap the '+' icon and trigger a frame.
await tester.tap(find.byIcon(Icons.add));
await tester.pump();
// Verify that our counter has incremented.
expect(find.text('0/90'), findsNothing);
expect(find.text('1/90'), findsOneWidget);
});
}