如何使用Provider将模拟注入Flutter测试

时间:2020-11-11 17:02:54

标签: flutter

我想使用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);
  });
}

0 个答案:

没有答案