繁体   English   中英

在颤振/飞镖中对未来错误进行单元测试的正确方法是什么?

[英]What is the proper way to unittest future errors in flutter/dart?

我正在编写的单元测试应该因异常而失败,我想匹配使用匹配器抛出的错误,但我收到了一个错误。

我目前做错了什么,这里的错误是什么? 如果我做错了,为返回未来的方法测试错误场景的正确方法是什么? 为什么会有异步间隙?

这是我要测试的方法:

Future<void> registerUser(String name, String email, String password) async {
auth.signUp(email, password, name).then((_) {
      auth.getCurrentUser().then((user) async {
        // Doing something
    }).catchError((onError) {
      throw onError;
    });

这是我写的测试:

test('should fail to register if fetching user fails', () async {
      MockAuth auth = MockAuth();
      RegisterRepository repo = RegisterRepository(auth);

      String password = 'password';
      String email = 'email';
      String name = 'name';

      when(auth.signUp(email, password, name))
          .thenAnswer((_) => Future.value());
      when(auth.getCurrentUser()).thenThrow((_) => throw Error());

      try {
        await repo.registerUser(name, email, password);
        fail('exception not thrown');
      } catch (e) {}

      verify(auth.signUp(email, password, name)).called(1);
      verify(auth.getCurrentUser()).called(1);
      verifyNoMoreInteractions(auth);
    });

我收到此错误:

package:mockito/src/mock.dart 403:7               PostExpectation.thenThrow.<fn>
package:mockito/src/mock.dart 130:45              Mock.noSuchMethod
package:dive/repository/register_repo.dart 25:12  RegisterRepository.registerUser.<fn>
===== asynchronous gap ===========================
dart:async                                        Future.then
package:dive/repository/register_repo.dart 24:40  RegisterRepository.registerUser
test/repository/register_repo_test.dart 61:20     main.<fn>.<fn>

Closure: (dynamic) => Null

对于将来面临这个问题的任何其他人,

  1. 我从正在测试的方法中删除了 async 关键字,这里不需要 async 关键字。 链接调用使其更具可读性:
Future<void> registerUser(String name, String email, String password) {
return auth
        .signUp(email, password, name)
        .then((_) => auth.getCurrentUser())
        .then((user) {
        // Doing something
    }).catchError((onError) {
      throw onError;
    });
  1. 要测试未来的错误,请执行以下操作:
test('should fail to register if fetching user fails', () async {
      MockAuth auth = MockAuth();
      RegisterRepository repo = RegisterRepository(auth);

      String password = 'password';
      String email = 'email';
      String name = 'name';

      when(auth.signUp(email, password, name))
          .thenAnswer((_) => Future.value());
      when(auth.getCurrentUser()).thenAnswer((_) => Future.error('error'));

      repo.registerUser(name, email, password).catchError((onError) {
        expect(onError.toString(), 'error');

        verify(auth.signUp(email, password, name)).called(1);
        verify(auth.getCurrentUser()).called(1);
        verifyNoMoreInteractions(auth);
      });
    });

现在测试通过了。

刚刚发现我们可以简单地做到这一点(查看throwsA ):

test("getNews SHOULD throw an exception WHEN api fails", () {
  final ExceptionMock exception = ExceptionMock();
  when(() => newsApi.getNews()).thenAnswer((realInvocation) => Future<List<JsonNews>>.error(exception));

  expect(() => sut.getNews(), throwsA(exception));
});

请注意,我是 mocking 例外。 这样,我确信实际上正在调用 api。 否则我不会捕捉到那个模拟的异常。 当使用具体的 object 时,无法确定是否返回了一个值,因为依赖项实际上返回了 object,或者它只是在 sun(被测系统)实现中硬编码。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM