好的,请耐心等待,因为我刚刚开始学习小部件测试。我有一个 MainAppBar 小部件,它在小部件树中的上方有一个 AuthProvider,如果用户实际上已通过身份验证,则需要执行身份验证检查和后续注销。这是一个愚蠢的场景,但能够测试它对于我的应用程序中的许多其他场景很有用。
IconButton(
icon: Icon(Icons.logout),
onPressed: () {
if (Provider.of<AuthProvider>(context, listen: false).isAuthenticated) {
Provider.of<AuthProvider>(context, listen: false).signOut();
Navigator.pushReplacementNamed(context, '/login');
}
}
)
我像这样嘲笑 AuthProvider
class MockAuthProvider extends Mock implements AuthProvider {}
使用 mockito 并像这样包装小部件
MockAuthProvider mockAuthProvider = MockAuthProvider();
Widget makeTestableWidget({Widget child}) => MaterialApp(
home: ChangeNotifierProvider<AuthProvider>(
create: (_) => mockAuthProvider,
child: Scaffold(
body: child,
),
),
);
bool是基于简单的isAuthenticated
枚举状态检查,所以只要设置状态,就可以测试真假场景等。在我的测试中,我想设置一个状态,测试是否调用了signOut
and 。Navigator
testWidgets('Clicking on logout icon...', (WidgetTester tester) async {
mockAuthProvider.setAuthProviderStatus(AuthProviderStatus.Unauthenticated);
print(mockAuthProvider.isAuthenticated);
await tester.pumpWidget(makeTestableWidget(child: MainAppBar(title: 'test')));
var icon = find.byIcon(Icons.logout);
await tester.tap(icon);
await tester.pump();
verifyNever(mockAuthProvider.signOut());
});
setAuthProviderStatus
setter 设置状态并进行isAuthenticated
基本检查:
bool get isAuthenticated {
if (status == AuthProviderStatus.Authenticated) {
return true;
}
return false;
}
AuthProvider 将状态初始化为默认值Uninitialized
,因此尽管可以将此检查扩展为考虑 null,但现在应该没问题。在我的 MainAppBar 小部件中,isAuthenticated
bool 以 null 的形式返回并抛出异常Failed assertion: boolean expression must not be null
,因为 if 语句需要 bool,而 null 会导致它失败。我的测试中的打印print(mockAuthProvider.isAuthenticated);
也是空的。我已经通过实际的 AuthProvider 成功进行了测试,并且没有遇到同样的问题,尽管这显然不适用于测试目的。
如何在模拟 Provider 中设置值,以便它们下面的小部件知道它们?