http - 单元测试 - 如何在颤振中模拟第三方库类 Dio 的参数
问题描述
我正在尝试测试一个简单的存储库类,它使用依赖注入的 Dio 包进行网络调用。Http.post 的要求是将 Map 对象发送到带有'Content-Type': 'application/json
. 您可以在下面看到:
class AuthenticateUserRemoteDataSourceImpl
implements AuthenticateUserRepository {
final Dio httpClient;
AuthenticateUserRemoteDataSourceImpl({@required this.httpClient});
@override
Future<Either<Failure, AuthenticateUser>> getAuthenticateUser(
String email, String password) async {
final url = 'API_URL';
final Map<String, String> jsonPayload = {
"email": email,
"password": password
};
Response response = await httpClient.post('{$url}api/users/authenticate',
data: jsonPayload,
options: Options(headers: {'Content-Type': 'application/json'}));
}
}
我试图确保单元测试涵盖此方法,但是我很难使用 Dio 包验证命名参数。我可以验证dioClient.post
实际调用了但是,我在模拟“数据”和“选项”的名称参数时遇到了麻烦。
我想测试它是否被Map<String, String>
正文调用,并且我想测试发送的标头,我想检查它是用{'Content-Type': 'application/json'}
. 当我需要对 Authenticated dio get/post/put 请求进行单元测试时,这也会很有用。
这是我到目前为止所做的测试,如前所述,我可以验证是否调用了模拟函数,但不能验证名称参数。
group('getAuthenticateUser', () {
final tResponse = Response(statusCode: 200, data: {"title": "success"});
test(
'should perform a post request to the the API with the application/json header',
() async {
// arrange
when(dioClient.post(any,
data: anyNamed('data'), options: anyNamed('options')))
.thenAnswer((Invocation invocation) async => tResponse);
// act
await dataSource.getAuthenticateUser(tEmail, tPassword);
// assert
verify(dioClient.post(any,
data: anyNamed('data'), options: anyNamed('options')));
});
});
感谢您的帮助,我刚刚开始进行单元测试,所以任何帮助或指示都会很棒,
谢谢,山姆
更新
我已经实现了你的模拟类,效果很好,我认为这是我肯定缺少的东西。我已经更新了我的测试,但不明白我现在哪里出错了?
测试.dart
class MockOptions extends Mock implements Options {
final Map<String, dynamic> headers;
//also add any other parameters you want to mock as fields in this class
MockOptions({this.headers});
}
test(
'should perform a post request to the the API with the application/json header',
() async {
// arrange
Map<String, String> headers = {'Content-type': 'application/json'};
when(mockDio.post('path', options: anyNamed('options')))
.thenAnswer((_) async => Response(data: {}));
// act
dataSource.getAuthenticateUser(tEmail, tPassword);
// assert
verify(mockDio.post('path', options: MockOptions(headers: headers)));
});
方法文件如下所示:
@override
Future<Either<Failure, AuthenticateUser>> getAuthenticateUser(
String email, String password) async {
await this.httpClient.post('path',
data: {},
options: Options(headers: {'Content-type': 'application/json'}));
}
解决方案
使用http_mock_adapter,用于模拟请求的新包Dio
。
您可以简单地将注入Dio
的 'shttpClientAdapter
替换DioAdapter()
为http_mock_adapter:
import 'package:dio/dio.dart';
import 'package:http_mock_adapter/http_mock_adapter.dart';
void main() async {
final dio = Dio();
final dioAdapter = DioAdapter();
dio.httpClientAdapter = dioAdapter;
const path = 'https://example.com';
dioAdapter
..onGet(
path,
(request) => request.reply(200, {'message': 'Successfully mocked GET!'}),
)
..onGet(
path,
(request) => request.reply(200, {'message': 'Successfully mocked POST!'}),
);
final onGetResponse = await dio.get(path);
print(onGetResponse.data); // {message: Successfully mocked GET!}
final onPostResponse = await dio.post(path);
print(onPostResponse.data); // {message: Successfully mocked POST!}
}
您也可以使用DioInterceptor
http_mock_adapter ,它可以添加到dio.interceptor
列表中。
在http_mock_adapter的示例文件中查看第二个示例
推荐阅读
- c# - 为什么实体框架给我一个关于不存在的现有数据的错误
- java - 安装 Eclim 时出错,“SKProfile”不是有效的标识符
- postgresql - PostgreSQL 9.4.1,级联删除时不要调用trigger
- python - PyMC 加权抽样
- javascript - 如何使用 Angular 6 从 iframe 获取数据
- javascript - 将 upTime 函数从 Javascript 转换为 Jquery,并对多个 ID 使用单个函数
- python - 如何访问 MMAX2 带注释的 XML 语料库中的数据
- generics - 在 java 中显式调用默认方法 - 当实现的接口使用泛型时
- lazarus - TProcess 中的 `free` 方法有什么作用?
- javascript - 两个带有常用下拉菜单的 D3.js 热图