Flutter 中 Provider 的单元测试
Unit Testing for Providers in Flutter
我们已经在 TDD 方法中启动了一个关于 Flutter 的新项目。我正在使用提供商进行状态管理。
在尝试编写 Widget 测试时,我们面临着测试提供者的问题。
你能举个例子来建议为提供者编写单元测试和小部件注入提供者吗?
我遇到了以下问题
══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════
The following ProviderNotFoundException was thrown running a test:
Error: Could not find the correct Provider above this SplashScreen Widget
To fix, please:
Ensure the Provider is an ancestor to this SplashScreen Widget
Provide types to Provider
Provide types to Consumer
Provide types to Provider.of()
Always use package imports. Ex: `import 'package:my_app/my_code.dart';
Ensure the correct context is being used.
══╡启动画面代码╞══════════════════════════════════
import 'dart:async';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../../../routes.dart';
import '../../constants/constants.dart';
import '../../providers/provider.dart';
import '../../services/navigation_service.dart';
import '../../utils/utlis.dart';
class SplashScreen extends StatefulWidget {
@override
SplashScreenState createState() => SplashScreenState();
}
class SplashScreenState extends State {
void startTime() {
const _duration = Duration(seconds: Preferences.splashScreenTime);
Timer(_duration, _getInitialData);
_getInitialData();
}
dynamic _getInitialData() async {
final TokenProvider tokenProvider =
Provider.of(context, listen: false);
await tokenProvider.setAccessToken();
navigationPage();
}
void navigationPage() {
NavigationService.pushReplacementNamedTo(Routes.home_screen);
}
@override
void initState() {
super.initState();
startTime();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: Stack(
key: const Key('splashScreen_body'),
fit: StackFit.expand,
children: [
Image.asset(
'assets/images/flutter.png',
key: const Key('splashScreen_image'),
)
],
),
);
}
}
提前致谢
您需要将要测试的小部件包装在该小部件使用的提供程序中。
因此,您可能想写:
await tester.pumpWidget(
Provider<TokenProvider>(
child: SplashScreen(),
),
);
如果你用这样的代码重复测试过,
你可以利用 extension
import 'package:provider/provider.dart';
import 'package:flutter/material.dart';
import 'package:mockito/mockito.dart';
Widget wrapWithMaterial() => MaterialApp(
home: Provider<TokenProvider>(
create: (_) => MockTokenProvider(),
child: Scaffold(
body: this,
),
),
);
class MockTokenProvider extends Mock implements TokenProvider {}
现在在你的测试中你可以
await tester.pumpWidget(
SplashScreen().wrapWithMaterial()
);
我们已经在 TDD 方法中启动了一个关于 Flutter 的新项目。我正在使用提供商进行状态管理。 在尝试编写 Widget 测试时,我们面临着测试提供者的问题。 你能举个例子来建议为提供者编写单元测试和小部件注入提供者吗?
我遇到了以下问题
══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════
The following ProviderNotFoundException was thrown running a test:
Error: Could not find the correct Provider above this SplashScreen Widget
To fix, please:
Ensure the Provider is an ancestor to this SplashScreen Widget
Provide types to Provider
Provide types to Consumer
Provide types to Provider.of()
Always use package imports. Ex: `import 'package:my_app/my_code.dart';
Ensure the correct context is being used.
══╡启动画面代码╞══════════════════════════════════
import 'dart:async';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../../../routes.dart';
import '../../constants/constants.dart';
import '../../providers/provider.dart';
import '../../services/navigation_service.dart';
import '../../utils/utlis.dart';
class SplashScreen extends StatefulWidget {
@override
SplashScreenState createState() => SplashScreenState();
}
class SplashScreenState extends State {
void startTime() {
const _duration = Duration(seconds: Preferences.splashScreenTime);
Timer(_duration, _getInitialData);
_getInitialData();
}
dynamic _getInitialData() async {
final TokenProvider tokenProvider =
Provider.of(context, listen: false);
await tokenProvider.setAccessToken();
navigationPage();
}
void navigationPage() {
NavigationService.pushReplacementNamedTo(Routes.home_screen);
}
@override
void initState() {
super.initState();
startTime();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: Stack(
key: const Key('splashScreen_body'),
fit: StackFit.expand,
children: [
Image.asset(
'assets/images/flutter.png',
key: const Key('splashScreen_image'),
)
],
),
);
}
}
提前致谢
您需要将要测试的小部件包装在该小部件使用的提供程序中。
因此,您可能想写:
await tester.pumpWidget(
Provider<TokenProvider>(
child: SplashScreen(),
),
);
如果你用这样的代码重复测试过,
你可以利用 extension
import 'package:provider/provider.dart';
import 'package:flutter/material.dart';
import 'package:mockito/mockito.dart';
Widget wrapWithMaterial() => MaterialApp(
home: Provider<TokenProvider>(
create: (_) => MockTokenProvider(),
child: Scaffold(
body: this,
),
),
);
class MockTokenProvider extends Mock implements TokenProvider {}
现在在你的测试中你可以
await tester.pumpWidget(
SplashScreen().wrapWithMaterial()
);