Flutter 如何从ChangeNotifier提供程序状态对值进行单元测试?
我在正在构建的应用程序中设置了登录/身份验证功能。我正在努力寻找一个示例/概念化的方法来进行单元测试 我的身份验证提供程序服务 我简化了一些事情Flutter 如何从ChangeNotifier提供程序状态对值进行单元测试?,flutter,flutter-test,Flutter,Flutter Test,我在正在构建的应用程序中设置了登录/身份验证功能。我正在努力寻找一个示例/概念化的方法来进行单元测试 我的身份验证提供程序服务 我简化了一些事情 import '../models/user.dart'; import 'package:http/http.dart' as http; enum Status { Uninitialized, Authenticated, Unauthenticated, LoginError, } class MyAuth with Cha
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();
}
}
下游小部件提交表单:
_user = Provider.of<MyAuth>;
....
return RaisedButton(
child: Text('Log In');
onPressed: () async {
await _user.login('username', 'password');
},
),
\u user=Provider.of;
....
返回上升按钮(
子项:文本(“登录”);
onPressed:()异步{
等待用户登录('username','password');
},
),
所有登录功能都正常工作,我希望能够测试的是提交
login()
方法,然后检查状态的值。如果有人能给我一个关于如何测试这个的包含示例,我将不胜感激。问题在于login()
方法本身,您将其称为“伪代码”,但整个测试代码将围绕它生成,因此我们需要该代码来帮助您
但是,即使没有login()
代码,我也可以给您一些关于如何实现测试的提示。首先看一看。基本上,您应该从测试中排除任何副作用和不稳定/缓慢的系统,如网络调用和数据库访问
为此,您可以进行一个伪API调用,该调用用于登录API,并在测试中注入该伪对象
让我们假设您使用FirebaseAuth作为身份验证API,因此您的代码将如下所示:
main.dart:
类MyApp扩展了无状态小部件{
//此小部件是应用程序的根。
@凌驾
小部件构建(构建上下文){
回程多供应商(
供应商:[
//为所有其他需要的对象注入真正的FirebaseAuth。
value(值:FirebaseAuth.instance),
//我们在这里注入真正的FirebaseAuth,以便MyAuth可以使用它。
ChangeNotifierProvider(创建:()=>MyAuth(FirebaseAuth.instance)),
],
孩子:MaterialApp(
标题:“颤振演示”,
onGenerateRoute:Router.generateRoute,
initialRoute:“/”,
));
}
}
login.dart:
(我不知道你怎么称呼它)
import'../models/user.dart';
将“package:http/http.dart”导入为http;
枚举状态{
未初始化,
认证,
未经认证,
登录错误,
}
使用ChangeNotifier类MyAuth{
//我们在此处注入FirebaseAuth:
MyAuth(this.\u auth):断言(\u auth!=null);
最终FirebaseAuth_auth;
UserModel\u用户;
状态_Status=状态。未初始化;
状态获取状态=>\u状态;
UserModel get user=>\u user;
未来登录(字符串电子邮件、字符串密码)异步{
//在这里使用auth!
_status=status.Authenticated;
notifyListeners();
}
}
现在,您使用的测试应该类似于以下内容:
import'包:mockito/mockito.dart';
类MockFirebaseAuth扩展了Mock实现FirebaseAuth{}
MockFirebaseAuth mockAuth;
...
设置((){
//在此处配置mockAuth的行为方式:
当(mockOldUser.reload()).thenAnswer(())异步{
返回null;
});
测试('用户登录',()异步{
//我们使用FirebaseAuth的假实例创建MyAuth并将其注入:
var auth=MyAuth(mockAuth);
等待auth.login();
expect(auth.status,等于(status.Authenticated));
});
这是一个如何实现的蓝图,我建议您阅读mocks如何使用Mockito工作,这样您就可以在测试中创建具有可预测行为的假实例(如“抛出错误”或“返回用户”),并在使用依赖项注入构建类时开始以不同的方式思考。谢谢您,这很有意义,我将进行测试并跟进。login()
函数只是向端点发出HTTP POST请求,该请求返回存储在用户
对象中的会话令牌。依赖项注入是有意义的,执行“真实”登录测试应该是我们集成测试的一部分(我已经有了工作)。是的,这是正确的,只需注入一个假的HTTP服务。
_user = Provider.of<MyAuth>;
....
return RaisedButton(
child: Text('Log In');
onPressed: () async {
await _user.login('username', 'password');
},
),