如何为dio超时创建测试 [英] How create test for dio timeout

查看:125
本文介绍了如何为dio超时创建测试的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用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 awaiting 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆