如何在Flutter中对超时进行单元测试?

4

我有一个门面函数,它重新加载当前的Firebase用户并返回它。问题是用户重新加载部分有一个超时时间,需要进行测试。

函数:

Future<Option<User>> getSignedInUser() async {
    // Reload currentUser if possible
    // it mustn't throw [TimeoutException] for whole function,
    // this is what this try/catch does
    try {
      await reloadCurrentUser().timeout(const Duration(seconds: 20));
    } catch (e) {
      log(e.toString(), name: TAG);
    }
    return optionOf(_auth.currentUser);
  }

reloadCurrentUser()函数:

Future<Either<AuthFailure, Unit>> reloadCurrentUser() async {
    try {
      await _auth.currentUser?.reload();
      return right(unit);
    } catch (e) {
      log(e.toString(), name: TAG);
      return left(const AuthFailure.userReloadingError());
    }
  }

问题是如何测试reloadCurrentUser()超时?我试图在调用此函数时抛出TimeoutException,但然后会将整个测试报错。
当前测试函数:
test(
        'Reaches timeout when reloading currentUser, '
        'throws TimeoutException, but function continues '
        'and returns optionOf currentUser', () async {
      reset(fakeFirebaseAuth);
      reset(fakeFacebookAuth);
      reset(fakeGoogleSignIn);

      final currentUser = FakeUser();

      // It says that currentUser exists and *IS* authenticated
      when(() => fakeFirebaseAuth.currentUser).thenReturn(currentUser);
      when(() => firebaseAuthFacade.reloadCurrentUser())
          .thenThrow(TimeoutException('timeout', const Duration(seconds: 20)));

      final result = await firebaseAuthFacade.getSignedInUser();

      expect(result, isA<Some<User>>());
    });

也许最好移除超时并使用一些连接性包来确保用户有网络连接,然后才重新加载当前用户?

为了进行测试,我正在使用mocktail包。

1个回答

0
你可以使用fake_async包。
以下是他们文档中的一个简单示例,你可以根据你的用例进行修改:
import 'dart:async';

import 'package:fake_async/fake_async.dart';
import 'package:test/test.dart';

void main() {
  test("Future.timeout() throws an error once the timeout is up", () {
    // Any code run within [fakeAsync] is run within the context of the
    // [FakeAsync] object passed to the callback.
    fakeAsync((async) {
      // All asynchronous features that rely on timing are automatically
      // controlled by [fakeAsync].
      expect(Completer().future.timeout(Duration(seconds: 5)),
          throwsA(isA<TimeoutException>()));

      // This will cause the timeout above to fire immediately, without waiting
      // 5 seconds of real time.
      async.elapse(Duration(seconds: 5));
    });
  });
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接