Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/flutter/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Flutter 如何从ChangeNotifier提供程序状态对值进行单元测试?_Flutter_Flutter Test - Fatal编程技术网

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');

 },
),