Flutter/Dart wait for a few seconds in unit testing
Asked Answered
R

2

45

I am writing a timer app. In unit testing how do I wait for few seconds to test if my timer is working properly?

// I want something like this.
test("Testing timer", () {
    int startTime = timer.seconds;
    timer.start();

    // do something to wait for 2 seconds

    expect(timer.seconds, startTime - 2);

});
Rice answered 8/1, 2019 at 9:5 Comment(0)
S
85

You can use awaitFuture.delayed(...)`:

test("Testing timer", () async {
    int startTime = timer.seconds;
    timer.start();

    // do something to wait for 2 seconds
    await Future.delayed(const Duration(seconds: 2), (){});

    expect(timer.seconds, startTime - 2);

});

An alternative would be fake_async with https://pub.dartlang.org/packages/clock to be able to freely manipulate the time used in the test.

Soane answered 8/1, 2019 at 9:6 Comment(2)
the await syntax does not seem to work. It says "await" is not a type. Do I need to import something for it to work?Rice
You are missing async somewhere. Please update your question with your current code.Sussex
W
3

The accepted answer is not optimal, as not all delays are just a few seconds long.

What if you had to test a 10-minute delay?

A better approach would be to use the fake_async package.

Here's an example from their docs that you can adjust for your use case:

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));
    });
  });
}

The above code also works with timers.

Wheelhorse answered 5/2, 2023 at 21:15 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.