如何为dio超时创建测试 [英] How create test for dio timeout
问题描述
我正在尝试使用Dio创建超时测试,我希望得到CONNECT_TIMEOUT类型的DioError然后抛出自定义异常
I am trying to create a test for timeout using Dio, I expect get DioError with type CONNECT_TIMEOUT then throw a custom exception
我的测试是使用Mockito模拟Dio,然后尝试抛出DioError
My test I mock Dio with Mockito and try throw DioError
test(
'Should throw [ConnectionTimeOutException] when reach timeout',
() async {
//arange
when(mockNetworkInfo.isConnected).thenAnswer((_) async => true);
when(mockDio.post(paths.login, data: tParams.toJson())).thenThrow(
(_) async => DioError(type: DioErrorType.CONNECT_TIMEOUT));
//act
final call = loginDataSource.login;
//assert
expect(() => call(params: tParams),
throwsA(TypeMatcher<ConnectTimeOutException>()));
},
);
我的数据源类:
class LoginDataSourceImpl implements LoginDataSource {
final Dio dio;
final NetworkInfo networkInfo;
LoginDataSourceImpl({@required this.dio, @required this.networkInfo});
@override
Future<CredencialModel> login({@required Params params}) async {
if (!await networkInfo.isConnected) {
throw NoNetworkException();
}
try {
final response = await dio.post(paths.login, data: params.toJson());
if (response.statusCode == 200) {
return CredencialModel.fromJson(response.data);
} else if (response.statusCode == 400) {
final error = ResponseError.fromJson(response.data);
switch (error.error) {
case 'invalid_request':
throw InvalidRequestException();
break;
case 'invalid_device':
throw InvalidDeviceException();
break;
case 'invalid_user_credentials':
throw InvalidUserCredentialException();
break;
case 'user_disabled':
throw UserDisableException();
default:
throw UnknowException();
}
} else if (response.statusCode == 500) {
throw ServerException();
} else {
throw UnknowException();
}
} on DioError catch (e) {
if (e.type == DioErrorType.CONNECT_TIMEOUT) {
throw ConnectTimeOutException();
} else if (e.type == DioErrorType.RECEIVE_TIMEOUT) {
} else {
throw UnknowException();
}
}
}
}
测试结果为:
Expected: throws <Instance of 'ConnectTimeOutException'>
Actual: <Closure: () => Future<CredencialModel>>
Which: threw <Closure: (dynamic) => DioError>
stack package:mockito/src/mock.dart 385:7
我该如何解决此问题并使用Dio创建超时测试?
How can i solve this issue and create a Timeout test with Dio?
推荐答案
您的方法存在两个问题.
There are a couple of problems with your approach.
首先,您正在测试 async
方法,但没有 await
.这将导致原始的 Future
对象返回到 expect
函数,该函数将认为它是成功的调用,即使将来最终抛出错误.您将需要等待
,尽管这样做会导致传递给 expect
的闭包很尴尬.我建议将异步调用包装在try/catch中.
First, you are testing an async
method but you are not await
ing it. This is going to cause the raw Future
object to be returned to the expect
function which is going to consider it a successful call, even if the future ends up throwing an error. You will need to await
your call, although doing so as a closure passed to expect
is awkward. I would suggest wrapping the asynchronous call in a try/catch instead.
第二,您提供了Mockito的 thenThrow
方法的闭包.该方法将您提供的所有内容都用作实际的抛出值,因此它不会调用传递给它的闭包-它将按原样抛出.
Second, you are providing a closure to Mockito's thenThrow
method. This method takes whatever you give to it and uses it as the actual thrown value, so it isn't going to call the closure you passed to it - it will just throw it as-is.
修复这两个问题,您最终会得到以下结果:
Fixing these both, you end up with this:
test(
'Should throw [ConnectionTimeOutException] when reach timeout',
() async {
// arrange
when(mockNetworkInfo.isConnected)
.thenAnswer(true);
when(mockDio.post(paths.login, data: tParams.toJson()))
.thenThrow(DioError(type: DioErrorType.CONNECT_TIMEOUT));
// act
final call = loginDataSource.login;
// assert
try {
await call(params: tParams);
} catch(e) {
expect(e, isInstanceOf<ConnectTimeOutException>());
}
},
);
这篇关于如何为dio超时创建测试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!