如何对来自更改通知程序提供程序状态的值进行单元测试?



我在正在构建的应用程序中设置了登录/身份验证功能。我正在努力寻找一个例子/概念化如何对此进行单元测试。

我的身份验证提供程序服务

我简化了一些事情。

import '../models/user.dart';
import 'package:http/http.dart' as http;
enum Status {
Uninitialized,
Authenticated,
Unauthenticated,
LoginError,
}
class MyAuth with ChangeNotifier {
UserModel _user;
Status _status = Status.Uninitialized;
Status get status => _status;
UserModel get user => _user;
Future<void> login(String email, String password) async {
await login(); //pseudo-code
_status = Status.Authenticated;
notifyListeners();
}
}

我如何调用

我的main.dart正在使用多提供程序:

class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => MyAuth()),
],
child: MaterialApp(
title: 'Flutter Demo',
onGenerateRoute: Router.generateRoute,
initialRoute: '/',
));
}
}

下游小组件提交表单:

_user = Provider.of<MyAuth>;
....
return RaisedButton(
child: Text('Log In');
onPressed: () async {
await _user.login('username', 'password');
},
),

所有登录功能都有效,我希望能够测试的是提交login()方法,然后检查Status的值。如果有人能给我一个如何测试的例子,我将不胜感激。

问题是login()方法本身,你把它称为"伪代码",但整个测试代码都是围绕它制作的,所以我们需要这些代码来帮助你。

但即使没有login()代码,我也可以给你一些关于如何实现测试的提示。首先看一下依赖注入。基本上,您应该从测试中排除任何副作用和易失性/缓慢系统,例如网络调用和数据库访问。

为此,您可以进行虚假的 API 调用,模拟您的登录 API 并在测试中注入该虚假对象。

假设您使用 FirebaseAuth 作为身份验证 API,因此您的代码将变为如下所示:

main.dart:

class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
// Inject a real FirebaseAuth for all other objects that wants it.
Provider<FirebaseAuth>.value(value: FirebaseAuth.instance), 
// We inject the real FirebaseAuth here so MyAuth can use it.
ChangeNotifierProvider(create: (_) => MyAuth(FirebaseAuth.instance)),
],
child: MaterialApp(
title: 'Flutter Demo',
onGenerateRoute: Router.generateRoute,
initialRoute: '/',
));
}
}

login.dart:(我不知道你是怎么称呼的(

import '../models/user.dart';
import 'package:http/http.dart' as http;
enum Status {
Uninitialized,
Authenticated,
Unauthenticated,
LoginError,
}
class MyAuth with ChangeNotifier {
// We inject the FirebaseAuth here:
MyAuth(this._auth) : assert(_auth != null);
final FirebaseAuth _auth;
UserModel _user;
Status _status = Status.Uninitialized;
Status get status => _status;
UserModel get user => _user;
Future<void> login(String email, String password) async {
// use _auth here!
_status = Status.Authenticated;
notifyListeners();
}
}

现在,使用mockito的测试应该类似于以下内容:

import 'package:mockito/mockito.dart';
class MockFirebaseAuth extends Mock implements FirebaseAuth {} 
MockFirebaseAuth mockAuth;
...
setUp(() {
// configure how mockAuth should behave here:
when(mockOldUser.reload()).thenAnswer((_) async {
return null;
});
test('User login', () async {
// we create MyAuth with a fake instance of FirebaseAuth and inject it:
var auth = MyAuth(mockAuth);
await auth.login();
expect(auth.status, equals(Status.Authenticated));
});

这是一个关于如何做到这一点的蓝图,我建议你阅读模拟如何使用 Mockito 工作,这样你就可以在测试中创建具有可预测行为的假实例(如"抛出错误"或"返回用户"(,并开始在构建类时以不同的方式思考,使用依赖注入。

相关内容

最新更新