Flutter Unit Test with Future.then

274
  1. Future<T>.catchError expects a callback that returns a Future<T>.

  2. However, Future.catchError is confusing to use, and it'd be better to avoid it entirely:

try {
  await A(bmock).doSomething();
  fail('doSomething did not throw');
} catch (e) {
  expect(e, 'error');
}

or you can use expectLater:

await expectLater(A(bmock).doSomething(), throwsA('error'));
Share:
274
0xPixelfrost
Author by

0xPixelfrost

Updated on January 03, 2023

Comments

  • 0xPixelfrost
    0xPixelfrost over 1 year

    I want to write a flutter unit test, where a future maps a result to something different and returns the new result again as future, like:

    Future<String> invoke() => class.doSomething().then((value) => map(value));
    

    The sample method "invoke()" should return the mapped value.


    The positive test, returning the mapped value, is working. (test1 in sample below)

    The negative test, returning an Future.error, fails with this error (test 2 in sample below):

    Invalid argument(s) (onError): The error handler of Future.catchError must return a value of the future's type

    Does anybody know how to improve the test so i can test the error case like described in test2:

    import 'package:mockito/annotations.dart';
    import 'package:mockito/mockito.dart';
    import 'package:test/test.dart';
    
    import 'test_test.mocks.dart';
    
    class A {
      final B b;
    
      A(this.b);
    
      Future<String> doSomething() => b.doSomething().then((value) => "mappedResult");
    }
    
    class B {
      Future<int> doSomething() => Future.delayed(const Duration(seconds: 1));
    }
    
    @GenerateMocks([B])
    void main() {
      final bmock = MockB();
    
      test('test1', () async {
        when(bmock.doSomething()).thenAnswer((_) => Future.value(1));
    
        var result = await A(bmock).doSomething();
    
        expect(result, "mappedResult");
      });
    
      test('test2', () async {
        when(bmock.doSomething()).thenAnswer((_) => Future.error("error"));
    
        A(bmock).doSomething().catchError((error) {
          expect(error, "error");
        });
      });
    }
    

    Versions:

      Flutter 2.10.1
      mockito: ^5.0.17
      test: ^1.17.12