docs

TOP(About this memo)) > 一覧(Dart) > fake_async/clockパッケージ

fake_async

// README.md記載のコード
void main() {
  test("Future.timeout() throws an error once the timeout is up", () {
     fakeAsync((async) {
      expect(Completer().future.timeout(const Duration(seconds: 5)),
          throwsA(isA<TimeoutException>()));

      async.elapse(const Duration(seconds: 5));
    });
  });
}
void main() {
  final fakeAsync = FakeAsync();
  final clock = fakeAsync.getClock(DateTime.utc(2023));
  print(clock.now());// 2023-01-01 00:00:00.000Z
  fakeAsync.elapse(const Duration(days: 3));
  print(clock.now());// 2023-01-04 00:00:00.000Z
}
void main() {
  fakeAsync((async) {
    print(clock.now());
    async.elapse(const Duration(days: 10));
    print(clock.now());
  }, initialTime: DateTime.utc(2001));
}

/*

2001-01-01 00:00:00.000Z
2001-01-11 00:00:00.000Z

*/
void main() {
  final fakeAsync = FakeAsync();
  fakeAsync.run((self) {
    Future(() => print("future"));
    Future.microtask(() => print("microtask1"));
    Future.microtask(() => print("microtask2"));
  });
  print("no microtask done yet.");
  fakeAsync.flushMicrotasks();
  print("no future done yet.");
  fakeAsync.flushTimers();

  /*

no microtask done yet.
microtask1
microtask2
no future done yet.
future

  */
}

(参考)FakeAsyncの実装

class FakeAsync {
  late final Clock _clock;
  Duration get elapsed => _elapsed;
  var _elapsed = Duration.zero;
  //...
  final _microtasks = Queue<_Microtask>();
  final _timers = <FakeTimer>{};
  //...
  FakeAsync({DateTime? initialTime, this.includeTimerStackTrace = true}) {
    var nonNullInitialTime = initialTime ?? clock.now();
    _clock = Clock(() => nonNullInitialTime.add(elapsed));
  }
  //...
}
T fakeAsync<T>(T Function(FakeAsync async) callback, {DateTime? initialTime}) =>
    FakeAsync(initialTime: initialTime).run(callback);
class FakeAsync {
  //...
  T run<T>(T Function(FakeAsync self) callback) =>
      runZoned(() => withClock(_clock, () => callback(this)),
          zoneSpecification: ZoneSpecification(
              createTimer: (_, __, ___, duration, callback) =>
                  _createTimer(duration, callback, false),
              createPeriodicTimer: (_, __, ___, duration, callback) =>
                  _createTimer(duration, callback, true),
              scheduleMicrotask: (_, __, ___, microtask) =>
                  _microtasks.add(microtask)));
  //...
// flutter/bin/cache/pkg/sky_engine/lib/async/timer.dart
abstract interface class Timer {
    //...
    factory Timer(Duration duration, void Function() callback) {
        if (Zone.current == Zone.root) {
        // No need to bind the callback. We know that the root's timer will
        // be invoked in the root zone.
        return Zone.current.createTimer(duration, callback);
        }
        return Zone.current
            .createTimer(duration, Zone.current.bindCallbackGuarded(callback));
    }
    //...
}
abstract interface class Timer {
  // ...
  static void run(void Function() callback) {
    new Timer(Duration.zero, callback);
  }
  // ...
}
// flutter/bin/cache/pkg/sky_engine/lib/async/future_impl.dart
class _Future<T> implements Future<T> {
  //...
  Future<T> timeout(Duration timeLimit, {FutureOr<T> onTimeout()?}) {
   //...
   timer = new Timer(timeLimit, () {/* ... */});
   //...
  }
  //...
}
// flutter/bin/cache/pkg/sky_engine/lib/async/future.dart
abstract interface class Future<T> {
  //...
  factory Future.delayed(Duration duration, [FutureOr<T> computation()?]) {
      // ...
      _Future<T> result = new _Future<T>();
      new Timer(duration, () {
          //...
          result._complete(computation());
          //...
      });
      return result;
      }
  //...
}

clock

// clock-1.1.1/lib/src/default.dart
Clock get clock => Zone.current[_clockKey] as Clock? ?? const Clock();

T withClock<T>(
  Clock clock,
  T Function() callback, {/* ... */}) {
  //...
  return runZoned(callback,
      zoneValues: {_clockKey: clock, _isFinalKey: isFinal});
}
// clock-1.1.1/lib/src/clock.dart
class Clock {
  final DateTime Function() _time;
  const Clock([DateTime Function() currentTime = systemTime])// DateTime systemTime() => DateTime.now();
      : _time = currentTime;
  Clock.fixed(DateTime time) : _time = (() => time);
  DateTime now() => _time();
  //...
}
void main() {
  withClock(Clock.fixed(DateTime.utc(2023)), () => print(clock.now()));
}
/*

2023-01-01 00:00:00.000Z

*/
import 'package:clock/clock.dart';
import 'package:fake_async/fake_async.dart';

void main() {
  fakeAsync((async) {
    print(clock.now());
    async.elapse(const Duration(days: 10));
    print(clock.now());
  }, initialTime: DateTime.utc(2001));// initialTimeを指定するとFakeAsync._clockの初期値として設定される。
}

/*

2001-01-01 00:00:00.000Z
2001-01-11 00:00:00.000Z

*/