Skip to content

Testing with Future.error #23

Closed

Description

@shripal17

I am trying to test my async function which accepts a Future and also returns a Future.
If the input Future throws an error, I handle it and return a -1 instead.

e.g.

Main Code

class Processor {
  Future<int> execute(Future<int> process) async {
    try {
      final result = await process;
      return result;
    } catch (e) {
      return -1;
    }
  }
}

Test

void main() {
  final processor = Processor();
  final process = Future.value(1);

  getErroneousProcess() => Future<int>.error(SignalException("something went wrong"));

  test('exception', () async {
    final result = await processor.execute(getErroneousProcess());
    expect(result, -1);
  });

  test('success', () async {
    final result = await processor.execute(process);
    expect(result, 1);
  });
}

Parameterized version

void main() {
  final processor = Processor();
  final process = Future.value(1);

  getErroneousProcess() => Future<int>.error(SignalException("something went wrong"));

  parameterizedTest(
    'process',
    [
      [getErroneousProcess(), -1],
      [process, 1],
    ],
    (process, expected) async {
      final result = await processor.execute(process);
      expect(result, expected);
    },
  );
}

Problem

Expectation

The parameterized version runs and tests code the same way as non-parameterized version.

Reality

The parameterized test fails with output did not complete [E]

$ flutter test

00:00 +0 -1: loading my_project/test/test_error.dart [E]                                                                                                                                                                                                               
  Failed to load "my_project/test/test_error.dart": something went wrong
  
00:00 +0 -1: process [ Instance of 'Future<int>', -1 ] - did not complete [E]                                                                                                                                                                                                                        
00:00 +0 -1: process [ Instance of 'Future<int>', 1 ] - did not complete [E]                                                                                                                                                                                                                         
00:00 +0 -1: Some tests failed.                

Activity

  1. Guldem commented on Jun 3, 2025

    @Guldem
    Member

    Thanks for reporting this , including a example. I have to look into this. I would suspected it to work the same.

  2. self-assigned this
    on Jun 3, 2025
  3. Guldem commented on Jun 27, 2025

    @Guldem
    Member

    I had some time to look into it and it looks like it has to do with how the Future.error is passed around. I don't really think its a bug.

    For example this results in the same issue:

    void main() {
      final processor = Processor();
      final process = Future.value(1);
    
       final getErroneousProcess = Future<int>.error('This also fails');
    
      test('exception', () async {
        final result = await processor.execute(getErroneousProcess);
        expect(result, -1);
      });
    
      test('success', () async {
        final result = await processor.execute(process);
        expect(result, 1);
      });
    }

    The problem is how the error is provided. For the parameterized version the callback isn't stored in the list but the value which causes the test to fail.

    To solve this in the parameterized version is to provide the correct callback like this:

    void main() {
      final processor = Processor();
    
      parameterizedTest(
        'process',
        [
          [() => Future<int>.error('This works'), -1],
          [() => Future<int>.value(1), 1],
        ],
        (Future<int> Function() process, int expected) async {
          final result = await processor.execute(process());
          expect(result, expected);
        },
      );
    }

    I hope this helps with your issue 😄

  4. shripal17 commented on Jun 29, 2025

    @shripal17
    Author

    Thanks for your time, that explains. So basically, the solution is to use supplier functions for Future.errors.
    Just an idea for you to consider: Maybe this is also worth documenting? 📚

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions